void ApplyBCsElement(PetscInt mx,PetscInt my, PetscInt mz, PetscInt i, PetscInt j, PetscInt k,PetscScalar *jacobian) { PetscInt ii,jj,kk,ll,ei,ej,ek,el; for (kk=0;kk<NB;kk++){ for (jj=0;jj<NB;jj++) { for (ii=0;ii<NB;ii++) { for(ll = 0;ll<3;ll++) { PetscInt tridx = ll + 3*(ii + jj*NB + kk*NB*NB); for (ek=0;ek<NB;ek++){ for (ej=0;ej<NB;ej++) { for (ei=0;ei<NB;ei++) { for (el=0;el<3;el++) { if (OnBoundary(i+ii,j+jj,k+kk,mx,my,mz) || OnBoundary(i+ei,j+ej,k+ek,mx,my,mz)) { PetscInt teidx = el + 3*(ei + ej*NB + ek*NB*NB); if (teidx == tridx) { jacobian[tridx + NPB*teidx] = 1.; } else { jacobian[tridx + NPB*teidx] = 0.; } } } } } } } } } } }
void GatherElementData(PetscInt mx,PetscInt my,PetscInt mz,Field ***x,CoordField ***c,PetscInt i,PetscInt j,PetscInt k,Field *ex,CoordField *ec,AppCtx *user) { PetscInt m; PetscInt ii,jj,kk; /* gather the data -- loop over element unknowns */ for (kk=0;kk<NB;kk++){ for (jj=0;jj<NB;jj++) { for (ii=0;ii<NB;ii++) { PetscInt idx = ii + jj*NB + kk*NB*NB; /* decouple the boundary nodes for the displacement variables */ if (OnBoundary(i+ii,j+jj,k+kk,mx,my,mz)) { BoundaryValue(i+ii,j+jj,k+kk,mx,my,mz,ex[idx],user); } else { for (m=0;m<3;m++) { ex[idx][m] = x[k+kk][j+jj][i+ii][m]; } } for (m=0;m<3;m++) { ec[idx][m] = c[k+kk][j+jj][i+ii][m]; } } } } }
bool CListContour::CompactStrips() { CLineStrip* pStrip; CLineStrip* pStripBase; size_t i; CLineStripList::iterator pos,pos2; CLineStripList newList; bool again, changed; const double weldDist = 10*(m_dDx*m_dDx+m_dDy*m_dDy); const size_t size = m_vStripLists.size(); assert__( size == GetNPlanes() ); for ( i = 0; i < size; i++ ) { if ( i == size / 2 ) mProgress( 1 ); again=true; while(again) { // REPEAT COMPACT PROCESS UNTILL LAST PROCESS MAKES NO CHANGE again=false; // building compacted list assert__(newList.empty()); for (pos=m_vStripLists[i].begin(); pos!=m_vStripLists[i].end(); pos++) { pStrip=(*pos); for (pos2=newList.begin(); pos2!=newList.end(); pos2++) { pStripBase=(*pos2); changed=MergeStrips(pStripBase,pStrip); if (changed) again=true; if (pStrip->empty()) break; } if (pStrip->empty()) delete pStrip; else newList.insert(newList.begin(),pStrip); } // deleting old list m_vStripLists[i].clear(); // Copying all for (pos2=newList.begin(); pos2 != newList.end(); pos2++) { pStrip=(*pos2); CLineStrip::iterator pos1 = pStrip->begin(),pos3; while (pos1!=pStrip->end()) { pos3 = pos1; pos3++; if ( pos3 != pStrip->end() && (*pos1) == (*pos3)) //femm, from if ( (*pos1) == (*pos3)) pStrip->erase(pos3); else pos1++; } //if (!(pStrip->front()==pStrip->back() && pStrip->size()==2)) if (pStrip->size()!=1) m_vStripLists[i].insert(m_vStripLists[i].begin(),pStrip ); else delete pStrip; } // emptying temp list newList.clear(); } // OF WHILE(AGAIN) (LAST COMPACT PROCESS MADE NO CHANGES) if (m_vStripLists[i].empty()) continue; /////////////////////////////////////////////////////////////////////// // compact more long_t Nstrip,j,index,count; Nstrip = m_vStripLists[i].size(); std::vector<bool> closed(Nstrip); double x,y; // First let's find the open and closed lists in m_vStripLists for(pos2 = m_vStripLists[i].begin(), j=0, count=0; pos2 != m_vStripLists[i].end(); pos2++, j++) { pStrip = (*pos2); // is it open ? if (pStrip->front() != pStrip->back()) { index = pStrip->front(); x = GetXi(index); y = GetYi(index); index = pStrip->back(); x -= GetXi(index); y -= GetYi(index); // is it "almost closed" ? if ( x*x+y*y < weldDist) closed[j] = true; else { closed[j] = false; // updating not closed counter... count ++; } } else closed[j] = true; } // is there any open strip ? if (count > 1) { // Merge the open strips into NewList pos = m_vStripLists[i].begin(); for(j=0; j<Nstrip; j++) { if (closed[j] == false ) { pStrip = (*pos); newList.insert(newList.begin(),pStrip); pos = m_vStripLists[i].erase(pos); } else pos ++; } // are they open strips to process ? while(newList.size()>1) { pStripBase = newList.front(); // merge the rest to pStripBase again = true; while (again) { again = false; pos = newList.begin(); for(pos++; pos!=newList.end();) { pStrip = (*pos); changed = ForceMerge(pStripBase,pStrip); if (changed) { again = true; delete pStrip; pos = newList.erase(pos); } else pos ++; } } // while(again) index = pStripBase->front(); x = GetXi(index); y = GetYi(index); index = pStripBase->back(); x -= GetXi(index); y -= GetYi(index); // if pStripBase is closed or not if (x*x+y*y < weldDist) { m_vStripLists[i].insert(m_vStripLists[i].begin(),pStripBase); newList.pop_front(); } else { if (OnBoundary(pStripBase)) { LOG_TRACE("# open strip ends on boundary, continue.\n"); m_vStripLists[i].insert(m_vStripLists[i].begin(),pStripBase); newList.pop_front(); } else { LOG_TRACE("unpaired open strip at 1!"); //newList.pop_front();//femmfemmfemmefemm //continue; //femmfemmfemmefemm return false; } } } // while(newList.size()>1); if (newList.size() ==1) { pStripBase = newList.front(); if (OnBoundary(pStripBase)) { LOG_TRACE("# open strip ends on boundary, continue.\n"); m_vStripLists[i].insert(m_vStripLists[i].begin(),pStripBase); newList.pop_front(); } else { LOG_TRACE("unpaired open strip at 2!"); DumpPlane(i); return false; } } newList.clear(); } else if (count == 1) { pos = m_vStripLists[i].begin(); for(j=0; j<Nstrip; j++) { if (closed[j] == false ) { pStripBase = (*pos); break; } pos ++; } if (OnBoundary(pStripBase)) { LOG_TRACE("# open strip ends on boundary, continue.\n"); } else { LOG_TRACE("unpaired open strip at 3!"); DumpPlane(i); return false; } } ////////////////////////////////////////////////////////////////////////////////////////////////// } return true; }
PetscErrorCode NonlinearGS(SNES snes,Vec X,Vec B,void *ptr) { /* values for each basis function at each quadrature point */ AppCtx *user = (AppCtx*)ptr; PetscInt i,j,k,l,m,n,s; PetscInt pi,pj,pk; Field ef[1]; Field ex[8]; PetscScalar ej[9]; CoordField ec[8]; PetscScalar pjac[9],pjinv[9]; PetscScalar pf[3],py[3]; PetscErrorCode ierr; PetscInt xs,ys,zs; PetscInt xm,ym,zm; PetscInt mx,my,mz; DM cda; CoordField ***c; Vec C; DM da; Vec Xl,Bl; Field ***x,***b; PetscInt sweeps,its; PetscReal atol,rtol,stol; PetscReal fnorm0 = 0.0,fnorm,ynorm,xnorm = 0.0; PetscFunctionBegin; ierr = SNESNGSGetSweeps(snes,&sweeps);CHKERRQ(ierr); ierr = SNESNGSGetTolerances(snes,&atol,&rtol,&stol,&its);CHKERRQ(ierr); ierr = SNESGetDM(snes,&da);CHKERRQ(ierr); ierr = DMGetLocalVector(da,&Xl);CHKERRQ(ierr); if (B) { ierr = DMGetLocalVector(da,&Bl);CHKERRQ(ierr); } ierr = DMGlobalToLocalBegin(da,X,INSERT_VALUES,Xl);CHKERRQ(ierr); ierr = DMGlobalToLocalEnd(da,X,INSERT_VALUES,Xl);CHKERRQ(ierr); if (B) { ierr = DMGlobalToLocalBegin(da,B,INSERT_VALUES,Bl);CHKERRQ(ierr); ierr = DMGlobalToLocalEnd(da,B,INSERT_VALUES,Bl);CHKERRQ(ierr); } ierr = DMDAVecGetArray(da,Xl,&x);CHKERRQ(ierr); if (B) ierr = DMDAVecGetArray(da,Bl,&b);CHKERRQ(ierr); ierr = DMGetCoordinateDM(da,&cda);CHKERRQ(ierr); ierr = DMGetCoordinatesLocal(da,&C);CHKERRQ(ierr); ierr = DMDAVecGetArray(cda,C,&c);CHKERRQ(ierr); ierr = DMDAGetInfo(da,0,&mx,&my,&mz,0,0,0,0,0,0,0,0,0);CHKERRQ(ierr); ierr = DMDAGetCorners(da,&xs,&ys,&zs,&xm,&ym,&zm);CHKERRQ(ierr); for (s=0;s<sweeps;s++) { for (k=zs; k<zs+zm; k++) { for (j=ys; j<ys+ym; j++) { for (i=xs; i<xs+xm; i++) { if (OnBoundary(i,j,k,mx,my,mz)) { BoundaryValue(i,j,k,mx,my,mz,x[k][j][i],user); } else { for (n=0;n<its;n++) { for (m=0;m<9;m++) pjac[m] = 0.; for (m=0;m<3;m++) pf[m] = 0.; /* gather the elements for this point */ for (pk=-1; pk<1; pk++) { for (pj=-1; pj<1; pj++) { for (pi=-1; pi<1; pi++) { /* check that this element exists */ if (i+pi >= 0 && i+pi < mx-1 && j+pj >= 0 && j+pj < my-1 && k+pk >= 0 && k+pk < mz-1) { /* create the element function and jacobian */ GatherElementData(mx,my,mz,x,c,i+pi,j+pj,k+pk,ex,ec,user); FormPBJacobian(-pi,-pj,-pk,ex,ec,ef,ej,user); /* extract the point named by i,j,k from the whole element jacobian and function */ for (l=0;l<3;l++) { pf[l] += ef[0][l]; for (m=0;m<3;m++) { pjac[3*m+l] += ej[3*m+l]; } } } } } } /* invert */ InvertTensor(pjac,pjinv,NULL); /* apply */ if (B) for (m=0;m<3;m++) { pf[m] -= b[k][j][i][m]; } TensorVector(pjinv,pf,py); xnorm=0.; for (m=0;m<3;m++) { x[k][j][i][m] -= py[m]; xnorm += PetscRealPart(x[k][j][i][m]*x[k][j][i][m]); } fnorm = PetscRealPart(pf[0]*pf[0]+pf[1]*pf[1]+pf[2]*pf[2]); if (n==0) fnorm0 = fnorm; ynorm = PetscRealPart(py[0]*py[0]+py[1]*py[1]+py[2]*py[2]); if (fnorm < atol*atol || fnorm < rtol*rtol*fnorm0 || ynorm < stol*stol*xnorm) break; } } } } } } ierr = DMDAVecRestoreArray(da,Xl,&x);CHKERRQ(ierr); ierr = DMLocalToGlobalBegin(da,Xl,INSERT_VALUES,X);CHKERRQ(ierr); ierr = DMLocalToGlobalEnd(da,Xl,INSERT_VALUES,X);CHKERRQ(ierr); ierr = DMRestoreLocalVector(da,&Xl);CHKERRQ(ierr); if (B) { ierr = DMDAVecRestoreArray(da,Bl,&b);CHKERRQ(ierr); ierr = DMRestoreLocalVector(da,&Bl);CHKERRQ(ierr); } ierr = DMDAVecRestoreArray(cda,C,&c);CHKERRQ(ierr); PetscFunctionReturn(0); }
PetscErrorCode FormFunctionLocal(DMDALocalInfo *info,Field ***x,Field ***f,void *ptr) { /* values for each basis function at each quadrature point */ AppCtx *user = (AppCtx*)ptr; PetscInt i,j,k,l; PetscInt ii,jj,kk; Field ef[NEB]; Field ex[NEB]; CoordField ec[NEB]; PetscErrorCode ierr; PetscInt xs=info->xs,ys=info->ys,zs=info->zs; PetscInt xm=info->xm,ym=info->ym,zm=info->zm; PetscInt xes,yes,zes,xee,yee,zee; PetscInt mx=info->mx,my=info->my,mz=info->mz; DM cda; CoordField ***c; Vec C; PetscFunctionBegin; ierr = DMGetCoordinateDM(info->da,&cda);CHKERRQ(ierr); ierr = DMGetCoordinatesLocal(info->da,&C);CHKERRQ(ierr); ierr = DMDAVecGetArray(cda,C,&c);CHKERRQ(ierr); ierr = DMDAGetInfo(info->da,0,&mx,&my,&mz,0,0,0,0,0,0,0,0,0);CHKERRQ(ierr); ierr = DMDAGetCorners(info->da,&xs,&ys,&zs,&xm,&ym,&zm);CHKERRQ(ierr); /* loop over elements */ for (k=zs; k<zs+zm; k++) { for (j=ys; j<ys+ym; j++) { for (i=xs; i<xs+xm; i++) { for (l=0;l<3;l++) { f[k][j][i][l] = 0.; } } } } /* element starts and ends */ xes = xs; yes = ys; zes = zs; xee = xs+xm; yee = ys+ym; zee = zs+zm; if (xs > 0) xes = xs - 1; if (ys > 0) yes = ys - 1; if (zs > 0) zes = zs - 1; if (xs+xm == mx) xee = xs+xm-1; if (ys+ym == my) yee = ys+ym-1; if (zs+zm == mz) zee = zs+zm-1; for (k=zes; k<zee; k++) { for (j=yes; j<yee; j++) { for (i=xes; i<xee; i++) { GatherElementData(mx,my,mz,x,c,i,j,k,ex,ec,user); FormElementJacobian(ex,ec,ef,NULL,user); /* put this element's additions into the residuals */ for (kk=0;kk<NB;kk++){ for (jj=0;jj<NB;jj++) { for (ii=0;ii<NB;ii++) { PetscInt idx = ii + jj*NB + kk*NB*NB; if (k+kk >= zs && j+jj >= ys && i+ii >= xs && k+kk < zs+zm && j+jj < ys+ym && i+ii < xs+xm) { if (OnBoundary(i+ii,j+jj,k+kk,mx,my,mz)) { for (l=0;l<3;l++) f[k+kk][j+jj][i+ii][l] = x[k+kk][j+jj][i+ii][l] - ex[idx][l]; } else { for (l=0;l<3;l++) f[k+kk][j+jj][i+ii][l] += ef[idx][l]; } } } } } } } } ierr = DMDAVecRestoreArray(cda,C,&c);CHKERRQ(ierr); PetscFunctionReturn(0); }
PetscErrorCode FormJacobianLocal(DMDALocalInfo *info,Field ***x,Mat jacpre,Mat jac,void *ptr) { /* values for each basis function at each quadrature point */ AppCtx *user = (AppCtx*)ptr; PetscInt i,j,k,m,l; PetscInt ii,jj,kk; PetscScalar ej[NPB*NPB]; PetscScalar vals[NPB*NPB]; Field ex[NEB]; CoordField ec[NEB]; PetscErrorCode ierr; PetscInt xs=info->xs,ys=info->ys,zs=info->zs; PetscInt xm=info->xm,ym=info->ym,zm=info->zm; PetscInt xes,yes,zes,xee,yee,zee; PetscInt mx=info->mx,my=info->my,mz=info->mz; DM cda; CoordField ***c; Vec C; PetscInt nrows; MatStencil col[NPB],row[NPB]; PetscScalar v[9]; PetscFunctionBegin; ierr = DMGetCoordinateDM(info->da,&cda);CHKERRQ(ierr); ierr = DMGetCoordinatesLocal(info->da,&C);CHKERRQ(ierr); ierr = DMDAVecGetArray(cda,C,&c);CHKERRQ(ierr); ierr = MatScale(jac,0.0);CHKERRQ(ierr); xes = xs; yes = ys; zes = zs; xee = xs+xm; yee = ys+ym; zee = zs+zm; if (xs > 0) xes = xs-1; if (ys > 0) yes = ys-1; if (zs > 0) zes = zs-1; if (xs+xm == mx) xee = xs+xm-1; if (ys+ym == my) yee = ys+ym-1; if (zs+zm == mz) zee = zs+zm-1; for (k=zes; k<zee; k++) { for (j=yes; j<yee; j++) { for (i=xes; i<xee; i++) { GatherElementData(mx,my,mz,x,c,i,j,k,ex,ec,user); FormElementJacobian(ex,ec,NULL,ej,user); ApplyBCsElement(mx,my,mz,i,j,k,ej); nrows = 0.; for (kk=0;kk<NB;kk++){ for (jj=0;jj<NB;jj++) { for (ii=0;ii<NB;ii++) { PetscInt idx = ii + jj*2 + kk*4; for (m=0;m<3;m++) { col[3*idx+m].i = i+ii; col[3*idx+m].j = j+jj; col[3*idx+m].k = k+kk; col[3*idx+m].c = m; if (i+ii >= xs && i+ii < xm+xs && j+jj >= ys && j+jj < ys+ym && k+kk >= zs && k+kk < zs+zm) { row[nrows].i = i+ii; row[nrows].j = j+jj; row[nrows].k = k+kk; row[nrows].c = m; for (l=0;l<NPB;l++) vals[NPB*nrows + l] = ej[NPB*(3*idx+m) + l]; nrows++; } } } } } ierr = MatSetValuesStencil(jac,nrows,row,NPB,col,vals,ADD_VALUES);CHKERRQ(ierr); } } } ierr = MatAssemblyBegin(jac,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(jac,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr); /* set the diagonal */ v[0] = 1.;v[1] = 0.;v[2] = 0.;v[3] = 0.;v[4] = 1.;v[5] = 0.;v[6] = 0.;v[7] = 0.;v[8] = 1.; for (k=zs; k<zs+zm; k++) { for (j=ys; j<ys+ym; j++) { for (i=xs; i<xs+xm; i++) { if (OnBoundary(i,j,k,mx,my,mz)) { for (m=0; m<3;m++) { col[m].i = i; col[m].j = j; col[m].k = k; col[m].c = m; } ierr = MatSetValuesStencil(jac,3,col,3,col,v,INSERT_VALUES);CHKERRQ(ierr); } } } } ierr = MatAssemblyBegin(jac,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(jac,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = DMDAVecRestoreArray(cda,C,&c);CHKERRQ(ierr); PetscFunctionReturn(0); }