void calc_stats(ElementType elementType, HashTable* El_Table, HashTable* NodeTable, int myid, MatProps* matprops, TimeProps* timeprops, StatProps* statprops, DischargePlanes* discharge, double d_time) { int i, iproc; double area = 0.0, max_height = 0.0; double cutoffvolume; /* the desired volume of material to take statistics from, this is portion is the one with the largest heights, for example sampling the 95% (by volume) of the pile with the largest heights, the fraction is set by STAT_VOL_FRAC define statement */ double cutoffheight = 0.0; /* a pile height criteria equivalent to the cutoffvolume, this criteria is found at each iteration */ double statvolume; /* volume where pile thickness >= cutoffheight statvolume >= cutoffvolume */ double realvolume = 0.0; /* the total volume on this processor or across processors */ double slopevolume = 0.0; /* volume used to determine the average slope in the direction of velocity, slopevolume<=statvolume because can't count cells with zero velocity */ double testpointheight = statprops->heightifreach; double testpointx = statprops->xyifreach[0]; double testpointy = statprops->xyifreach[1]; double testpointdist2; double testpointmindist2; testpointmindist2 = pow(2.0, 30.0); //HUGE_VAL; int testpointreach = 0; double testvolume = 0.0; double slope_ave = 0.0; double v_max = 0.0, v_ave = 0.0, vx_ave = 0.0, vy_ave = 0.0, g_ave; double xC = 0.0, yC = 0.0, rC = 0.0, piler2 = 0.0; double xVar = 0.0, yVar = 0.0; //assume that mean starting location is at (x,y) = (1,1) double xCen = 1.2; //0; //1.0/(matprops->LENGTH_SCALE); double yCen = 0.3; //0; //1.0/(matprops->LENGTH_SCALE); double dVol, dA; double min_height = matprops->MAX_NEGLIGIBLE_HEIGHT; double temp; int numproc; double xyminmax[4]; for(i = 0; i < 4; i++) xyminmax[i] = HUGE_VAL; MPI_Comm_size(MPI_COMM_WORLD, &numproc); /* need to allocate space to store nonzero pile heights and volumes, to do that we first have to count the number of nonzero elements */ int num_buck = El_Table->get_no_of_buckets(); HashEntryPtr* buck = El_Table->getbucketptr(); int num_nonzero_elem = 0, *all_num_nonzero_elem; for(i = 0; i < num_buck; i++) if(*(buck + i)) { HashEntryPtr currentPtr = *(buck + i); while (currentPtr) { Element* Curr_El = (Element*) (currentPtr->value); if((Curr_El->get_adapted_flag() > 0) && (myid == Curr_El->get_myprocess())) if(*(Curr_El->get_state_vars()) > GEOFLOW_TINY) num_nonzero_elem++; currentPtr = currentPtr->next; } } /******************************************************************/ /*** the rewrite involves a sort which increases the cost/time ***/ /*** significantly and does not appear to provide a significant ***/ /*** increase in accuracy of the statistics (it probably makes ***/ /*** them LESS precise/repeatable actually) so the section of ***/ /*** code has been disabled by the following preprocessor ***/ /*** directive. ***/ /******************************************************************/ #ifdef NONONONO printf("NONONONO\n"); /* now we need to tell processor 0 how many there are, so it can allocate space for when it combine their contributions to come up with a cut off height */ MPI_Request request, *proc0request; MPI_Status status, *proc0status; //fprintf(fp,"calc_stats() 2\n"); fflush(fp); if(numproc>1) { if(myid==0) { proc0request=(MPI_Request *) calloc(numproc,sizeof(MPI_Request)); proc0status=(MPI_Status *) calloc(numproc,sizeof(MPI_Status)); all_num_nonzero_elem=CAllocI1(numproc); all_num_nonzero_elem[0]=num_nonzero_elem; for(iproc=1;iproc<numproc;iproc++) MPI_Irecv(&all_num_nonzero_elem[iproc],1,MPI_INT,iproc,1,MPI_COMM_WORLD,&proc0request[iproc]); } else MPI_Isend(&num_nonzero_elem,1,MPI_INT,0,1,MPI_COMM_WORLD,&request); } //fprintf(fp,"calc_stats() 3\n"); fflush(fp); /* now each processor generates a list of pile heights and volumes for each nonzero element sorted in descending order */ double **myprochvol=CAllocD2(num_nonzero_elem,2); double height; int iplace; num_nonzero_elem=0; realvolume=0.0; for(i=0; i<num_buck; i++) if(*(buck+i)) { HashEntryPtr currentPtr = *(buck+i); while(currentPtr) { Element* Curr_El=(Element*)(currentPtr->value); if((Curr_El->get_adapted_flag()>0)&& (myid==Curr_El->get_myprocess())) { height=*(Curr_El->get_state_vars()); if(height>GEOFLOW_TINY) { /* place this height in right (sorted in descending order) spot in height/volume arrray */ for(iplace=num_nonzero_elem;iplace>0;iplace--) if(height>myprochvol[iplace-1][0]) { myprochvol[iplace][0]=myprochvol[iplace-1][0]; myprochvol[iplace][1]=myprochvol[iplace-1][1];} else break; myprochvol[iplace][0]=height; myprochvol[iplace][1]=height* *(Curr_El->get_dx())**(Curr_El->get_dx()+1); realvolume+=myprochvol[iplace][1]; num_nonzero_elem++; } } currentPtr=currentPtr->next; } } /* now processor zero will use those list(s) to determine the cut off height */ if(numproc==1) { //it's for a single processor so it's very simple cutoffvolume=STAT_VOL_FRAC*realvolume; statvolume =0.0; i=0; while((statvolume<cutoffvolume)&&(i<num_nonzero_elem)) { cutoffheight=myprochvol[i][0]; statvolume +=myprochvol[i++][1]; } CDeAllocD2(myprochvol); } else { // to get a clear idea of what I want to do take a look // at the single processor version (the else to this if) // and ask your self what you would need to do if instead // of one array of sorted heights-volume pairs, you had // numproc of them... that is at every step you look at // the largest not yet counted height from each array and // add the largest ones volume to the total //fprintf(fp,"calc_stats() 4\n"); fflush(fp); //add up the real volume across all processors temp=realvolume; MPI_Reduce(&temp,&realvolume,1,MPI_DOUBLE,MPI_SUM,0,MPI_COMM_WORLD); if(myid>0) { //send my processor's list of height and volume to processor 0 //fprintf(fp,"calc_stats() 5\n"); fflush(fp); MPI_Isend(myprochvol[0],num_nonzero_elem*2,MPI_DOUBLE,0,2,MPI_COMM_WORLD,&request); } else { //this is processor zero, myid==0 //fprintf(fp,"calc_stats() 6\n"); fflush(fp); //allocate one big 3D array to hold all the lists from across //all processors MPI_Waitall(numproc-1,proc0request+1,proc0status+1); int max_num_nonzero_elem=num_nonzero_elem; for(iproc=1;iproc<numproc;iproc++) if(max_num_nonzero_elem<all_num_nonzero_elem[iproc]) max_num_nonzero_elem=all_num_nonzero_elem[iproc]; double ***hvol=CAllocD3(numproc,max_num_nonzero_elem,2); //fprintf(fp,"calc_stats() 7\n"); fflush(fp); //bring the individual processors' sorted lists of height and //volume (hvol) over to processor 0 for(iproc=1;iproc<numproc;iproc++) MPI_Irecv(hvol[iproc][0],all_num_nonzero_elem[iproc]*2,MPI_DOUBLE,iproc,2,MPI_COMM_WORLD,&proc0request[iproc]); for(i=0;i<all_num_nonzero_elem[0];i++) { hvol[0][i][0]=myprochvol[i][0]; hvol[0][i][1]=myprochvol[i][1];} //fprintf(fp,"calc_stats() 8\n"); fflush(fp); MPI_Waitall(numproc-1,proc0request+1,proc0status+1); free(proc0request); free(proc0status); //fprintf(fp,"calc_stats() 9\n"); fflush(fp); /* find the cut off height that results in statvolume= STAT_VOL_FRAC*realvolume statvolume= volume represented in stats realvolume= total volume */ cutoffvolume=STAT_VOL_FRAC*realvolume; statvolume =0.0; int *icurrent=CAllocI1(numproc); //fprintf(fp,"calc_stats() 10\n"); fflush(fp); //set the current "element" on each "processor" to the one with //the maximum height on that processor (the first one) for(iproc=0;iproc<numproc;iproc++) icurrent[iproc]=0; int imaxh=0; //check to see if the cut off height is small enough that we have //equaled or exceeded the cut off volume while((statvolume<cutoffvolume)&& (icurrent[imaxh]<max_num_nonzero_elem)) { //find the largest height among the "current" elements and make //it the cut off height for(iproc=0;iproc<numproc;iproc++) if((icurrent[iproc]<all_num_nonzero_elem[iproc])&& (hvol[iproc][icurrent[iproc]][0]> hvol[imaxh][icurrent[imaxh]][0])) imaxh=iproc; cutoffheight=hvol[imaxh][icurrent[imaxh]][0]; //add that element's volume to the total statvolume +=hvol[imaxh][icurrent[imaxh]++][1]; } //fprintf(fp,"calc_stats() 11\n"); fflush(fp); CDeAllocD3(hvol); CDeAllocI1(all_num_nonzero_elem); CDeAllocI1(icurrent); } //fprintf(fp,"calc_stats() 12\n"); fflush(fp); CDeAllocD2(myprochvol); //fprintf(fp,"calc_stats() 13\n"); fflush(fp); MPI_Bcast(&cutoffheight,1,MPI_DOUBLE,0,MPI_COMM_WORLD); //fprintf(fp,"calc_stats() 14\n"); fflush(fp); } #endif /**************************************************/ /****** TADA!!!!!!!!! we have finally found ******/ /****** this iteration's cut off height (and ******/ /****** the global volumes too) now we can ******/ /****** calculate the rest of the stats in a ******/ /****** straight forward manner ******/ /**************************************************/ //for TWO PHASES double Vsolid[2]; double Vfluid[2]; //for SINGLE PHASE double VxVy[2]; for(i = 0; i < num_buck; i++) if(*(buck + i)) { HashEntryPtr currentPtr = *(buck + i); while (currentPtr) { Element* Curr_El = (Element*) (currentPtr->value); assert(Curr_El!=NULL); if((Curr_El->get_adapted_flag() > 0) && (myid == Curr_El->get_myprocess())) { double* state_vars = Curr_El->get_state_vars(); //calculate volume passing through "discharge planes" unsigned *nodes = Curr_El->getNode(); Node** nodesPtr = Curr_El->getNodesPtrs(); double nodescoord[9][2], *coord; Node* node; for(int inode = 0; inode < 8; inode++) { node = nodesPtr[inode]; //(Node*) NodeTable->lookup(nodes + 2 * inode); coord = node->get_coord(); /*if ((timeprops->iter == 291) && (inode == 8)) { printf("coord=(%g,%g) node=%u ", coord[0], coord[1], node); fflush(stdout); }*/ nodescoord[inode][0] = coord[0]; nodescoord[inode][1] = coord[1]; /*if ((timeprops->iter == 291) && (inode >= 8)) { printf("inode=%d node=%u", inode, node); fflush(stdout); }*/ } nodescoord[8][0] = *(Curr_El->get_coord()); nodescoord[8][1] = *(Curr_El->get_coord() + 1); discharge->update(nodescoord, state_vars, d_time); // rule out non physical fast moving thin layers //if(state_vars[0] >= cutoffheight){ if(state_vars[0] > min_height) { if(state_vars[0] > max_height) max_height = state_vars[0]; double* xy = Curr_El->get_coord(); if(state_vars[0] >= statprops->hxyminmax) { if(xy[0] < xyminmax[0]) //xmin xyminmax[0] = xy[0]; if(-xy[0] < xyminmax[1]) //negative xmax xyminmax[1] = -xy[0]; if(xy[1] < xyminmax[2]) //ymin xyminmax[2] = xy[1]; if(-xy[1] < xyminmax[3]) //negative ymax xyminmax[3] = -xy[1]; } //to test if pileheight of depth testpointheight //has reached the testpoint testpointdist2 = (xy[0] - testpointx) * (xy[0] - testpointx) + (xy[1] - testpointy) * (xy[1] - testpointy); double junktest = 0; if(testpointdist2 > 0) junktest = testpointdist2; if(testpointmindist2 > 0) junktest = testpointmindist2; if(testpointdist2 < testpointmindist2) { testpointmindist2 = testpointdist2; testpointreach = ((state_vars[0] >= testpointheight) ? 1 : 0); } dA = *(Curr_El->get_dx()) * *(Curr_El->get_dx() + 1); area += dA; dVol = state_vars[0] * dA; testvolume += dVol; xC += xy[0] * dVol; yC += xy[1] * dVol; xVar += xy[0] * xy[0] * dVol; yVar += xy[1] * xy[1] * dVol; piler2 += (xy[0] * xy[0] + xy[1] * xy[1]) * dVol; rC += sqrt((xy[0] - xCen) * (xy[0] - xCen) + (xy[1] - yCen) * (xy[1] - yCen)) * dVol; if(elementType == ElementType::TwoPhases) { v_ave += sqrt(state_vars[2] * state_vars[2] + state_vars[3] * state_vars[3]) * dA; Curr_El->eval_velocity(0.0, 0.0, Vsolid); if((!((v_ave <= 0.0) || (0.0 <= v_ave))) || (!((state_vars[0] <= 0.0) || (0.0 <= state_vars[0]))) || (!((state_vars[1] <= 0.0) || (0.0 <= state_vars[1]))) || (!((state_vars[2] <= 0.0) || (0.0 <= state_vars[2]))) || (!((state_vars[3] <= 0.0) || (0.0 <= state_vars[3]))) || (!((state_vars[4] <= 0.0) || (0.0 <= state_vars[4]))) || (!((state_vars[5] <= 0.0) || (0.0 <= state_vars[5])))) { //v_ave is NaN printf("calc_stats(): NaN detected in element={%10u,%10u} at iter=%d\n", *(Curr_El->pass_key() + 0), *(Curr_El->pass_key() + 1), timeprops->iter); printf("prevu={%12.6g,%12.6g,%12.6g,%12.6g,%12.6g,%12.6g}\n", *(Curr_El->get_prev_state_vars() + 0), *(Curr_El->get_prev_state_vars() + 1), *(Curr_El->get_prev_state_vars() + 2), *(Curr_El->get_prev_state_vars() + 3), *(Curr_El->get_prev_state_vars() + 4), *(Curr_El->get_prev_state_vars() + 5)); printf(" u={%12.6g,%12.6g,%12.6g,%12.6g,%12.6g,%12.6g}\n", state_vars[0], state_vars[1], state_vars[2], state_vars[3], state_vars[4], state_vars[5]); printf("prev {Vx_s, Vy_s, Vx_f, Vy_f}={%12.6g,%12.6g,%12.6g,%12.6g}\n", *(Curr_El->get_prev_state_vars() + 2) / (*(Curr_El->get_prev_state_vars() + 1)), *(Curr_El->get_prev_state_vars() + 3) / (*(Curr_El->get_prev_state_vars() + 1)), *(Curr_El->get_prev_state_vars() + 4) / (*(Curr_El->get_prev_state_vars())), *(Curr_El->get_prev_state_vars() + 5) / (*(Curr_El->get_prev_state_vars()))); printf("this {Vx_s, Vy_s, Vx_f, Vy_f}={%12.6g,%12.6g,%12.6g,%12.6g}\n", state_vars[2] / state_vars[1], state_vars[3] / state_vars[1], state_vars[4] / state_vars[0], state_vars[5] / state_vars[0]); ElemBackgroundCheck2(El_Table, NodeTable, Curr_El, stdout); exit(1); } temp = sqrt(Vsolid[0] * Vsolid[0] + Vsolid[1] * Vsolid[1]); if(temp > v_max) v_max = temp; vx_ave += state_vars[2] * dA; vy_ave += state_vars[3] * dA; } if(elementType == ElementType::SinglePhase) { v_ave += sqrt(state_vars[1] * state_vars[1] + state_vars[2] * state_vars[2]) * dA; Curr_El->eval_velocity(0.0, 0.0, VxVy); if((!((v_ave <= 0.0) || (0.0 <= v_ave))) || (!((state_vars[0] <= 0.0) || (0.0 <= state_vars[0]))) || (!((state_vars[1] <= 0.0) || (0.0 <= state_vars[1]))) || (!((state_vars[2] <= 0.0) || (0.0 <= state_vars[2])))) { //v_ave is NaN printf("calc_stats(): NaN detected in element={%10u,%10u} at iter=%d\n", *(Curr_El->pass_key() + 0), *(Curr_El->pass_key() + 1), timeprops->iter); printf("prevu={%12.6g,%12.6g,%12.6g}\n", *(Curr_El->get_prev_state_vars() + 0), *(Curr_El->get_prev_state_vars() + 1), *(Curr_El->get_prev_state_vars() + 2)); printf(" u={%12.6g,%12.6g,%12.6g}\n", state_vars[0], state_vars[1], state_vars[2]); printf("prev {hVx/h,hVy/h}={%12.6g,%12.6g}\n", *(Curr_El->get_prev_state_vars() + 1) / *(Curr_El->get_prev_state_vars() + 0), *(Curr_El->get_prev_state_vars() + 2) / *(Curr_El->get_prev_state_vars() + 0)); printf("this {hVx/h,hVy/h}={%12.6g,%12.6g}\n", state_vars[1] / state_vars[0], state_vars[2] / state_vars[0]); printf(" { Vx , Vy }={%12.6g,%12.6g}\n", VxVy[0], VxVy[1]); ElemBackgroundCheck2(El_Table, NodeTable, Curr_El, stdout); assert(0); } temp = sqrt(VxVy[0] * VxVy[0] + VxVy[1] * VxVy[1]); if(temp > v_max) v_max = temp; vx_ave += state_vars[1] * dA; vy_ave += state_vars[2] * dA; } //these are garbage, Bin Yu wanted them when he was trying to come up //with a global stopping criteria (to stop the calculation, not the pile) //volume averaged slope in the direction of velocity //a negative number means the flow is headed uphill double resolution = 0, xslope = 0, yslope = 0; Get_max_resolution(&resolution); Get_slope(resolution, *((Curr_El->get_coord())) * matprops->LENGTH_SCALE, *((Curr_El->get_coord()) + 1) * matprops->LENGTH_SCALE, &xslope, &yslope); if(temp > GEOFLOW_TINY) { if(elementType == ElementType::TwoPhases) { slope_ave += -(state_vars[2] * xslope + state_vars[3] * yslope) * dA / temp; } if(elementType == ElementType::SinglePhase) { slope_ave += -(state_vars[1] * xslope + state_vars[2] * yslope) * dA / temp; } slopevolume += dVol; } } } currentPtr = currentPtr->next; } } MPI_Reduce(xyminmax, statprops->xyminmax, 4, MPI_DOUBLE, MPI_MIN, 0, MPI_COMM_WORLD); if(myid == 0) { statprops->xyminmax[0] *= (matprops->LENGTH_SCALE); statprops->xyminmax[1] *= -(matprops->LENGTH_SCALE); statprops->xyminmax[2] *= (matprops->LENGTH_SCALE); statprops->xyminmax[3] *= -(matprops->LENGTH_SCALE); } int inttempout; double tempin[14], tempout[14], temp2in[2], temp2out[2]; //find the minimum distance (squared) to the test point MPI_Allreduce(&testpointmindist2, tempout, 1, MPI_DOUBLE, MPI_MIN, MPI_COMM_WORLD); //if this processor isn't the closest to the test point it doesn't count as it's flow reaching the point if(tempout[0] < testpointmindist2) testpointreach = 0; //did the closest point to the test point get reached by the flow? MPI_Reduce(&testpointreach, &inttempout, 1, MPI_INT, MPI_MAX, 0, MPI_COMM_WORLD); testpointreach = inttempout; tempin[0] = xC; tempin[1] = yC; tempin[2] = rC; tempin[3] = area; tempin[4] = v_ave; tempin[5] = vx_ave; tempin[6] = vy_ave; tempin[7] = slope_ave; tempin[8] = piler2; tempin[9] = slopevolume; tempin[10] = testvolume; tempin[11] = xVar; tempin[12] = yVar; tempin[13] = El_Table->get_no_of_entries(); i = MPI_Reduce(tempin, tempout, 14, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD); temp2in[0] = max_height; temp2in[1] = v_max; i = MPI_Reduce(temp2in, temp2out, 2, MPI_DOUBLE, MPI_MAX, 0, MPI_COMM_WORLD); if(myid == 0) { if(testpointreach && (statprops->timereached < 0.0)) statprops->timereached = timeprops->timesec(); double VELOCITY_SCALE = sqrt(matprops->LENGTH_SCALE * matprops->GRAVITY_SCALE); //dimensionalize statprops->xcen = tempout[0] * (matprops->LENGTH_SCALE) / tempout[10]; statprops->ycen = tempout[1] * (matprops->LENGTH_SCALE) / tempout[10]; statprops->xvar = tempout[11] * (matprops->LENGTH_SCALE) * (matprops->LENGTH_SCALE) / tempout[10] - (statprops->xcen) * (statprops->xcen); statprops->yvar = tempout[12] * (matprops->LENGTH_SCALE) * (matprops->LENGTH_SCALE) / tempout[10] - (statprops->ycen) * (statprops->ycen); statprops->rmean = tempout[2] * (matprops->LENGTH_SCALE) / tempout[10]; statprops->area = tempout[3] * (matprops->LENGTH_SCALE) * (matprops->LENGTH_SCALE); statprops->vmean = tempout[4] * VELOCITY_SCALE / tempout[10]; statprops->vxmean = tempout[5] * VELOCITY_SCALE / tempout[10]; statprops->vymean = tempout[6] * VELOCITY_SCALE / tempout[10]; statprops->slopemean = (tempout[9] > 0) ? tempout[7] / tempout[9] : 0.0; statprops->realvolume = realvolume * (matprops->LENGTH_SCALE) * (matprops->LENGTH_SCALE) * (matprops->HEIGHT_SCALE); //statvolume is really testvolume which is statvolume if it's not disabled statprops->statvolume = tempout[10] * (matprops->LENGTH_SCALE) * (matprops->LENGTH_SCALE) * (matprops->HEIGHT_SCALE); statprops->cutoffheight = cutoffheight * (matprops->HEIGHT_SCALE); testvolume = tempout[10] / statvolume; /* the factor of 3^0.5 is a safety factor, this value was chosen because * it makes the "radius" of a uniformly distributed line equal to half * the line length */ //3 standard deviations out ~ 99.5% of the material statprops->piler = 3.0 * sqrt(statprops->xvar + statprops->yvar); statprops->hmax = temp2out[0] * (matprops->HEIGHT_SCALE); statprops->vmax = temp2out[1] * VELOCITY_SCALE; /* v_star is the nondimensional global average velocity by v_slump once v_slump HAS BEEN CALIBRATED (not yet done see ../main/datread.C) the calculation will terminate when v_star reaches 1 */ statprops->vstar = statprops->vmean / matprops->Vslump; /******************/ /* output section */ /******************/ /* output Center Of Mass and x and y components of mean velocity to assist the dynamic gis update daemon */ if(elementType == ElementType::SinglePhase) { FILE* fp2 = fopen("com.up", "w"); fprintf(fp2, "%d %g %g %g %g %g %g\n", timeprops->iter, timeprops->timesec(), statprops->xcen, statprops->ycen, statprops->vxmean, statprops->vymean, statprops->piler); fclose(fp2); } /* standard to screen output */ d_time *= timeprops->TIME_SCALE; //chunk time int hours, minutes; double seconds; timeprops->chunktime(&hours, &minutes, &seconds); printf("At the end of time step %d the time is %d:%02d:%g (hrs:min:sec),\n", timeprops->iter, hours, minutes, seconds); printf("\ttime step length is %g [sec], volume is %g [m^3],\n", d_time, statprops->statvolume); printf("\tmax height is %g [m], max velocity is %g [m/s],\n", statprops->hmax, statprops->vmax); printf("\tave velocity is %g [m/s], v* = %g,\n", statprops->vmean, statprops->vstar); printf("\ttotal number of elements %.0f\n\n", tempout[13]); } return; }
void cxxTitanSimulation::init_piles() { MatProps* matprops_ptr = get_matprops(); FluxProps* fluxprops_ptr = get_fluxprops(); TimeProps* timeprops_ptr = get_timeprops(); StatProps* statprops_ptr = get_statprops(); ElementsHashTable* HT_Elem_Ptr=get_HT_Elem(); NodeHashTable* HT_Node_Ptr=get_HT_Node(); PileProps* pileprops_ptr=get_pileprops(); unsigned nodes[9][KEYLENGTH], *node_key; int no_of_buckets = HT_Elem_Ptr->get_no_of_buckets(); vector<HashEntryLine> &bucket=HT_Elem_Ptr->bucket; tivector<Element> &elenode_=HT_Elem_Ptr->elenode_; PileProps::PileType pile_type= pileprops_ptr->get_default_piletype(); int i; bool allPilesAreElliptical=true; for(i=0;i<pileprops_ptr->numpiles;i++) { if(!(pileprops_ptr->pile_type[i] == PileProps::PARABALOID || pileprops_ptr->pile_type[i] == PileProps::CYLINDER)) allPilesAreElliptical=false; } if(pileprops_ptr->numpiles>0)pile_type= pileprops_ptr->pile_type[0]; if(!adapt) H_adapt_to_level(HT_Elem_Ptr, HT_Node_Ptr, matprops_ptr, pileprops_ptr, fluxprops_ptr, timeprops_ptr, REFINE_LEVEL); if(allPilesAreElliptical) { if(adapt) initial_H_adapt(HT_Elem_Ptr, HT_Node_Ptr, 0, matprops_ptr, pileprops_ptr, fluxprops_ptr, timeprops_ptr, 4); } else { printf("It seems this type of piles have hardcoded coordinates\n"); assert(0); //@ElementsBucketDoubleLoop for(int ibuck = 0; ibuck < no_of_buckets; ibuck++) { for(int ielm = 0; ielm < bucket[ibuck].ndx.size(); ielm++) { Element *EmTemp = &(elenode_[bucket[ibuck].ndx[ielm]]); if(EmTemp->adapted_flag() > 0) { //put in the pile height right here... double pile_height = 0.0; double radius_sq; switch (pile_type) { case PileProps::PLANE: radius_sq = pow(EmTemp->coord(0) - 76., 2) + pow(EmTemp->coord(1) - 80., 2); if(radius_sq < 35.) pile_height = 10 * (1. - radius_sq / 35.); break; case PileProps::CASITA: radius_sq = pow(EmTemp->coord(0) - 504600., 2) + pow(EmTemp->coord(1) - 1402320., 2); if(radius_sq < 30000.) pile_height = 15 * (1. - radius_sq / 30000.); break; case PileProps::POPO: //popo topo radius_sq = pow(EmTemp->coord(0) - 537758. / matprops_ptr->scale.length, 2) + pow(EmTemp->coord(1) - 2100910. / matprops_ptr->scale.length, 2); if(radius_sq < (10000. / matprops_ptr->scale.length)) pile_height = 1. - radius_sq / (10000. / matprops_ptr->scale.length); break; case PileProps::ID1: // iverson and denlinger experiments I -- as pictured if(EmTemp->coord(0) < 53.345 && EmTemp->coord(0) > 45.265 && EmTemp->coord(1) > -10. && EmTemp->coord(1) < 300.) { if(EmTemp->coord(0) < 51.148) pile_height = 3.5912 * (1.0 - (51.148 - EmTemp->coord(0)) / 5.8832); else pile_height = 3.59 * (53.345 - EmTemp->coord(0)) / 2.1967; if(pile_height < 0) pile_height = 0; } break; case PileProps::ID2: //iverson and denlinger experiments II -- 90 angle with plane if(EmTemp->coord(0) < 53.345 / matprops_ptr->scale.length && EmTemp->coord(0) > 46.45 / matprops_ptr->scale.length) pile_height = 4.207255 * (1.0 - (53.345 / matprops_ptr->scale.length - EmTemp->coord(0)) / 6.895 * matprops_ptr->scale.length); break; default: printf("Danger no recognized pile type defined in init_piles.C\n"); assert(0); } EmTemp->put_height(pile_height); } } } } //end "#if defined PARABALOID || defined CYLINDER" move_data(numprocs, myid, HT_Elem_Ptr, HT_Node_Ptr, timeprops_ptr); //update temporary arrays of elements/nodes pointers HT_Node_Ptr->flushNodeTable(); HT_Elem_Ptr->flushElemTable(); HT_Elem_Ptr->updateLocalElements(); HT_Elem_Ptr->updateNeighboursIndexes(); slopes(HT_Elem_Ptr, HT_Node_Ptr, matprops_ptr); /* initial calculation of actual volume on the map */ double realvolume = 0.0, depositedvol = 0.0, forcebed = 0.0, meanslope = 0.0; double epsilon[DIMENSION]; for(i=0;i<DIMENSION;i++) epsilon[i]=matprops_ptr->scale.epsilon; //@ElementsBucketDoubleLoop for(int ibuck = 0; ibuck < no_of_buckets; ibuck++) { for(int ielm = 0; ielm < bucket[ibuck].ndx.size(); ielm++) { Element* Curr_El = &(elenode_[bucket[ibuck].ndx[ielm]]); if(Curr_El->adapted_flag() > 0) { //if this is a refined element don't involve!!! double dvol = Curr_El->dx(0) * Curr_El->dx(1) * Curr_El->state_vars(0); realvolume += dvol; Curr_El->set_kactxy(epsilon); Curr_El->calc_stop_crit(matprops_ptr,integrator); if(Curr_El->stoppedflags() == 2) depositedvol += dvol; double resolution = 0, xslope = 0, yslope = 0; Get_max_resolution(&resolution); Get_slope(resolution, Curr_El->coord(0) * matprops_ptr->scale.length, Curr_El->coord(1) * matprops_ptr->scale.length, xslope, yslope); double slope = sqrt(xslope * xslope + yslope * yslope); forcebed += dvol * 9.8 / sqrt(1.0 + slope * slope) * tan(matprops_ptr->bedfrict[Curr_El->material()]); } } } double tempin[3], tempout[3]; tempin[0] = realvolume; tempin[1] = forcebed; tempin[2] = depositedvol; #ifdef USE_MPI MPI_Reduce(tempin, tempout, 3, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD); #else //USE_MPI for(int i9=0;i9<3;++i9)tempout[i9]=tempin[i9]; #endif //USE_MPI statprops_ptr->realvolume = tempout[0] * (matprops_ptr->scale.height) * (matprops_ptr->scale.length) * (matprops_ptr->scale.length); statprops_ptr->outflowvol = 0.0; statprops_ptr->erodedvol = 0.0; statprops_ptr->depositedvol = tempout[2] * (matprops_ptr->scale.height) * (matprops_ptr->scale.length) * (matprops_ptr->scale.length); statprops_ptr->forceint = 0.0; statprops_ptr->forcebed = tempout[1] / tempout[0]; return; }
void init_piles(HashTable* HT_Elem_Ptr, HashTable* HT_Node_Ptr, int myid, int numprocs, int adaptflag, MatProps* matprops, TimeProps* timeprops_ptr, MapNames* mapnames, PileProps* pileprops, FluxProps *fluxprops, StatProps* statprops) { unsigned nodes[9][KEYLENGTH], *node_key; int num_buckets=HT_Elem_Ptr->get_no_of_buckets(); if(!adaptflag) H_adapt_to_level(HT_Elem_Ptr,HT_Node_Ptr,matprops,pileprops, fluxprops,timeprops_ptr,REFINE_LEVEL); #if defined PARABALOID || defined CYLINDER if(adaptflag) initial_H_adapt(HT_Elem_Ptr, HT_Node_Ptr, 0, matprops, pileprops,fluxprops,timeprops_ptr,4); #else for(int ibucket=0; ibucket<num_buckets; ibucket++) { HashEntry *entryp = *(HT_Elem_Ptr->getbucketptr() + ibucket); //check every element in bucket while(entryp){ Element *EmTemp = (Element*)entryp->value; assert(EmTemp); if(EmTemp->get_adapted_flag()>0) { //put in the pile height right here... double* ndcoord = EmTemp->get_coord(); double pile_height=0.0; double radius_sq; EmTemp->put_height(pileheight); } entryp = entryp->next; } } #endif //end "#if defined PARABALOID || defined CYLINDER" move_data(numprocs, myid, HT_Elem_Ptr, HT_Node_Ptr,timeprops_ptr); slopes(HT_Elem_Ptr, HT_Node_Ptr, matprops); /* initial calculation of actual volume on the map */ double realvolume=0.0, depositedvol=0.0, forcebed=0.0, meanslope=0.0; double epsilon[2]={matprops->epsilon, matprops->epsilon}; HashEntryPtr* buck = HT_Elem_Ptr->getbucketptr(); for(int ibucket=0; ibucket<HT_Elem_Ptr->get_no_of_buckets(); ibucket++) if(*(buck+ibucket)) { HashEntryPtr currentPtr = *(buck+ibucket); while(currentPtr) { Element* Curr_El=(Element*)(currentPtr->value); assert(Curr_El); if(Curr_El->get_adapted_flag()>0) { //if this is a refined element don't involve!!! double *dxy=Curr_El->get_dx(); double dvol=dxy[0]*dxy[1]**(Curr_El->get_state_vars()+1); realvolume+=dvol; Curr_El->put_kactxy(epsilon); Curr_El->calc_stop_crit(matprops); if (Curr_El->get_stoppedflags()==2) depositedvol += dvol; double resolution=0, xslope=0, yslope=0; Get_max_resolution(&resolution); Get_slope(resolution, *((Curr_El->get_coord()))*matprops->LENGTH_SCALE, *((Curr_El->get_coord())+1)*matprops->LENGTH_SCALE, &xslope,&yslope); double slope=sqrt(xslope*xslope+yslope*yslope); forcebed+=dvol*9.8/sqrt(1.0+slope*slope)* tan(matprops->bedfrict[Curr_El->get_material()]); Curr_El->level_set(HT_Elem_Ptr); } currentPtr=currentPtr->next; } } //========================================================================================================================= for(int ibucket=0; ibucket<HT_Elem_Ptr->get_no_of_buckets(); ibucket++) if(*(buck+ibucket)) { HashEntryPtr currentPtr = *(buck+ibucket); while(currentPtr) { Element* Curr_El=(Element*)(currentPtr->value); assert(Curr_El); if(Curr_El->get_adapted_flag()>0) { if(*( Curr_El->get_state_vars()+5)==3) *(Curr_El->get_state_vars())=0.0;//to make zero phi on the boundary } currentPtr=currentPtr->next; } } double tempin[3], tempout[3]; tempin[0]=realvolume; tempin[1]=forcebed; tempin[2]=depositedvol; MPI_Reduce(tempin,tempout,3,MPI_DOUBLE,MPI_SUM,0,MPI_COMM_WORLD); statprops->realvolume=tempout[0]*(matprops->HEIGHT_SCALE) *(matprops->LENGTH_SCALE)*(matprops->LENGTH_SCALE); statprops->outflowvol=0.0; statprops->erodedvol=0.0; statprops->depositedvol=tempout[2]*(matprops->HEIGHT_SCALE) *(matprops->LENGTH_SCALE)*(matprops->LENGTH_SCALE); statprops->forceint=0.0; statprops->forcebed=tempout[1]/tempout[0]; return; }