314 std::cerr<<
"Begin computeDiffusiveFlux()"<<std::endl;
321 apf::MeshEntity* bent,*ent;
322 apf::MeshIterator* iter = m->begin(
nsd-1);
325 while(bent = m->iterate(iter)){
326 apf::MeshElement* b_elem;
327 b_elem = apf::createMeshElement(m,bent);
328 numbqpt = apf::countIntPoints(b_elem,
int_order);
329 apf::destroyMeshElement(b_elem);
334 diffFlux = m->createDoubleTag(
"diffFlux",numbqpt*
nsd*2);
335 apf::MeshElement* tempelem; apf::Element * tempvelo,*temppres,*tempvoff;
336 apf::MeshElement* b_elem;
337 apf::Adjacent adjFaces;
338 apf::Vector3 normal,centerdir;
340 double tempflux[numbqpt*
nsd];
341 double *flux; flux = (
double*) calloc(numbqpt*
nsd*2,
sizeof(
double));
342 apf::NewArray <double> shpval;
343 apf::NewArray <double> shpval_temp;
345 apf::FieldShape* err_shape = apf::getHierarchic(2);
346 apf::EntityShape* elem_shape;
347 apf::Vector3 bqpt,bqptl,bqptshp;
350 apf::Matrix3x3 tempgrad_velo;
351 apf::Matrix3x3 identity(1.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,1.0);
353 iter=m->begin(
nsd-1);
354 while(ent=m->iterate(iter))
356 m->setDoubleTag(ent,diffFlux,flux);
362 std::cerr<<
"Initialized flux"<<std::endl;
364 PCU_Comm_Begin(PCUObj);
365 iter = m->begin(
nsd);
367 while(ent = m->iterate(iter))
371 nshl=apf::countElementNodes(err_shape,m->getType(ent));
372 shpval_temp.allocate(nshl);
374 shpval.allocate(nshl);
375 elem_shape = err_shape->getEntityShape(m->getType(ent));
378 m->getAdjacent(ent,
nsd-1,adjFaces);
379 for(
int adjcount =0;adjcount<adjFaces.getSize();adjcount++){
380 bent = adjFaces[adjcount];
382 centerdir=apf::getLinearCentroid(m,ent)-apf::getLinearCentroid(m,bent);
384 if(
isInSimplex(m,ent,apf::project(normal,centerdir).normalize()*centerdir.getLength()+apf::getLinearCentroid(m,bent),
nsd)){
392 b_elem = apf::createMeshElement(m,bent);
393 tempelem = apf::createMeshElement(m,ent);
394 temppres = apf::createElement(pref,tempelem);
395 tempvelo = apf::createElement(velf,tempelem);
396 tempvoff = apf::createElement(voff,tempelem);
398 for(
int l = 0;l<numbqpt;l++)
400 apf::Vector3 bflux(0.0,0.0,0.0);
401 apf::Matrix3x3 tempbflux(0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0);
402 apf::getIntPoint(b_elem,
int_order,l,bqpt);
403 weight = apf::getIntWeight(b_elem,
int_order,l);
404 apf::getJacobian(b_elem,bqpt,J);
405 Jdet=fabs(apf::getJacobianDeterminant(J,
nsd-1));
406 bqptl=apf::boundaryToElementXi(m,bent,ent,bqpt);
407 apf::getVectorGrad(tempvelo,bqptl,tempgrad_velo);
408 tempgrad_velo = apf::transpose(tempgrad_velo);
410 apf::ModelEntity* me=m->toModel(bent);
411 int tag = m->getModelTag(me);
412 apf::ModelEntity* boundary_face = m->findModelEntity(
nsd-1,tag);
414 if(me==boundary_face && has_gBC){
416 double fluxdata[4][numbqpt];
420 m->getIntTag(bent,
BCtag,&(BCtype[0]));
421 if((BCtype[1]+BCtype[2]+BCtype[3] != 3) && BCtype[1] == 1 ){
422 std::cerr <<
"diffusive flux not fully specified on face " <<
localNumber(bent) <<
'\n';
423 std::cerr <<
"BCtype "<<BCtype[1]<<
" "<<BCtype[2]<<
" "<<BCtype[3]<<std::endl;
426 if(BCtype[1]+BCtype[2]+BCtype[3] == 3){
427 for(
int i=1;i<
nsd+1;i++)
428 m->getDoubleTag(bent,
fluxtag[i],&(fluxdata[i][0]));
429 bflux = apf::Vector3(fluxdata[1][l],fluxdata[2][l],fluxdata[3][l]);
430 bflux = bflux-identity*apf::getScalar(temppres,bqptl)/
getMPvalue(apf::getScalar(tempvoff,bqptl),
rho_0,
rho_1)*normal;
433 tempbflux = (tempgrad_velo+apf::transpose(tempgrad_velo))*
getMPvalue(apf::getScalar(tempvoff,bqptl),
nu_0,
nu_1)
434 -identity*apf::getScalar(temppres,bqptl)/
getMPvalue(apf::getScalar(tempvoff,bqptl),
rho_0,
rho_1);
435 bflux = tempbflux*normal;
439 tempbflux = (tempgrad_velo+apf::transpose(tempgrad_velo))*
getMPvalue(apf::getScalar(tempvoff,bqptl),
nu_0,
nu_1)
440 -identity*apf::getScalar(temppres,bqptl)/
getMPvalue(apf::getScalar(tempvoff,bqptl),
rho_0,
rho_1);
441 bflux = tempbflux*normal;
443 bflux = bflux*weight*Jdet;
449 for(
int d = 0; d <
nsd; d++) tempflux[l*
nsd+d] = bflux[d];
451 flux = (
double*) calloc(numbqpt*
nsd*2,
sizeof(
double));
452 m->getDoubleTag(bent,diffFlux,flux);
453 for (
int i=0;i<numbqpt*
nsd;i++){
454 flux[orientation*numbqpt*
nsd+i] = tempflux[i];
456 m->setDoubleTag(bent,diffFlux,flux);
458 apf::destroyMeshElement(tempelem);apf::destroyElement(tempvelo);apf::destroyElement(temppres); apf::destroyElement(tempvoff);
461 apf::ModelEntity* me=m->toModel(bent);
462 apf::ModelEntity* boundary_face = m->findModelEntity(
nsd-1,m->getModelTag(me));
464 if(m->isShared(bent))
466 m->getRemotes(bent,remotes);
467 for(apf::Copies::iterator it=remotes.begin(); it!=remotes.end();++it)
469 PCU_COMM_PACK(PCUObj, it->first, it->second);
470 PCU_COMM_PACK(PCUObj, it->first, orientation);
471 PCU_COMM_PACK(PCUObj, it->first, tempflux);
479 std::cerr<<
"Sending flux"<<std::endl;
480 PCU_Comm_Send(PCUObj);
481 flux = (
double*) calloc(numbqpt*
nsd*2,
sizeof(
double));
482 while(PCU_Comm_Receive(PCUObj))
484 PCU_COMM_UNPACK(PCUObj, bent);
485 PCU_COMM_UNPACK(PCUObj, orientation);
486 PCU_COMM_UNPACK(PCUObj, tempflux);
487 m->getDoubleTag(bent,diffFlux,flux);
488 for (
int i=0;i<numbqpt*
nsd;i++){
489 flux[orientation*numbqpt*
nsd+i] = flux[orientation*numbqpt*
nsd+i]+tempflux[i];
491 m->setDoubleTag(bent,diffFlux,flux);
496 std::cerr<<
"End computeDiffusiveFlux()"<<std::endl;
509 apf::NewArray <double> shpval;
510 apf::NewArray <double> shpval_temp;
513 apf::FieldShape* err_shape = apf::getHierarchic(2);
514 apf::EntityShape* elem_shape;
517 apf::Adjacent boundaries;
518 apf::MeshEntity* bent;
519 apf::MeshElement* b_elem;
520 apf::Vector3 bqpt,bqptl,bqptshp;
523 apf::Vector3 centerdir;
526 nshl=apf::countElementNodes(err_shape,m->getType(ent));
527 shpval_temp.allocate(nshl);
534 shpval.allocate(nshl);
535 elem_shape = err_shape->getEntityShape(m->getType(ent));
537 m->getAdjacent(ent,
nsd-1,boundaries);
538 for(
int adjcount =0;adjcount<boundaries.getSize();adjcount++){
540 apf::Vector3 bflux(0.0,0.0,0.0);
541 bent = boundaries[adjcount];
543 b_elem = apf::createMeshElement(m,bent);
545 centerdir=apf::getLinearCentroid(m,ent)-apf::getLinearCentroid(m,bent);
548 if(
isInSimplex(m,ent,apf::project(normal,centerdir).normalize()*centerdir.getLength()+apf::getLinearCentroid(m,bent),
nsd)){
549 normal = normal*-1.0;
552 apf::ModelEntity* me=m->toModel(bent);
553 int tag = m->getModelTag(me);
554 apf::ModelEntity* boundary_face = m->findModelEntity(
nsd-1,tag);
556 double flux_weight[2];
557 if(me==boundary_face){
558 if(orientation==0){flux_weight[0]=1; flux_weight[1]=0;}
559 else{flux_weight[0]=0; flux_weight[1]=-1;}
562 if(orientation==0){flux_weight[0]=(1-
a_kl); flux_weight[1]=
a_kl;}
563 else{ flux_weight[0]=-
a_kl; flux_weight[1]=-1*(1-
a_kl);}
566 int numbqpt = apf::countIntPoints(b_elem,
int_order);
567 flux = (
double*) calloc(numbqpt*
nsd*2,
sizeof(
double));
568 m->getDoubleTag(bent,diffFlux,flux);
569 for(
int l=0; l<numbqpt;l++){
570 apf::getIntPoint(b_elem,
int_order,l,bqpt);
571 bqptshp=apf::boundaryToElementXi(m,bent,ent,bqpt);
572 elem_shape->getValues(NULL,NULL,bqptshp,shpval_temp);
573 for(
int j=0;j<nshl;j++){shpval[j] = shpval_temp[hier_off+j];}
574 for(
int i=0;i<
nsd;i++){
575 for(
int s=0;
s<nshl;
s++){
576 endflux[i*nshl+
s] = endflux[i*nshl+
s]+(flux_weight[0]*flux[l*
nsd+i]+flux_weight[1]*flux[numbqpt*
nsd+l*
nsd+i])*shpval[
s];
692 nsd = m->getDimension();
695 apf::Field* voff = m->findField(
"vof");
697 apf::Field* velf = m->findField(
"velocity");
699 apf::Field* pref = m->findField(
"p");
711 freeField(errRho_reg);
712 freeField(errRel_reg);
714 err_reg = apf::createField(m,
"ErrorRegion",apf::SCALAR,apf::getVoronoiShape(
nsd,1));
715 errRho_reg = apf::createField(m,
"ErrorDensity",apf::SCALAR,apf::getVoronoiShape(
nsd,1));
716 errRel_reg = apf::createField(m,
"RelativeError",apf::SCALAR,apf::getVoronoiShape(
nsd,1));
724 apf::FieldShape* err_shape = apf::getHierarchic(
approx_order);
725 apf::Field * estimate = apf::createField(m,
"err_est", apf::VECTOR, err_shape);
726 apf::EntityShape* elem_shape;
728 apf::MeshElement* element;
729 apf::Element* visc_elem, *pres_elem,*velo_elem,*vof_elem;
730 apf::Element* est_elem;
733 apf::NewArray <double> shpval;
734 apf::NewArray <double> shpval_temp;
735 apf::NewArray <apf::Vector3> shgval;
737 apf::DynamicMatrix invJ_copy;
738 apf::NewArray <apf::DynamicVector> shdrv;
739 apf::NewArray <apf::DynamicVector> shgval_copy;
741 apf::MeshIterator* iter = m->begin(
nsd);
742 apf::MeshEntity* ent;
746 double err_est_total=0;
747 long nLocalSolveFailures=0;
748 double u_norm_total=0;
750 while(ent = m->iterate(iter)){
752 elem_type = m->getType(ent);
753 if(!(elem_type != 4 || elem_type != 2)){
754 std::cout<<
"Not a Tri or Tet present"<<std::endl;
757 element = apf::createMeshElement(m,ent);
758 pres_elem = apf::createElement(pref,element);
759 velo_elem = apf::createElement(velf,element);
760 visc_elem = apf::createElement(visc,element);
761 vof_elem = apf::createElement(voff,element);
763 numqpt=apf::countIntPoints(element,
int_order);
764 nshl=apf::countElementNodes(err_shape,elem_type);
765 shgval.allocate(nshl);
766 shpval_temp.allocate(nshl);
773 nshl = nshl - hier_off;
775 shpval.allocate(nshl); shgval_copy.allocate(nshl); shdrv.allocate(nshl);
778 int ndofs = nshl*
nsd;
780 MatCreate(PETSC_COMM_SELF,&K);
781 MatSetSizes(K,ndofs,ndofs,ndofs,ndofs);
782 MatSetFromOptions(K);
787 VecCreate(PETSC_COMM_SELF,&F);
788 VecSetSizes(F,ndofs,ndofs);
792 for(
int k=0;k<numqpt;k++){
793 apf::getIntPoint(element,
int_order,k,qpt);
794 apf::getJacobian(element,qpt,J);
795 J = apf::transpose(J);
799 Jdet=fabs(apf::getJacobianDeterminant(J,
nsd));
800 weight = apf::getIntWeight(element,
int_order,k);
801 invJ_copy = apf::fromMatrix(invJ);
804 elem_shape = err_shape->getEntityShape(elem_type);
805 elem_shape->getValues(NULL,NULL,qpt,shpval_temp);
806 elem_shape->getLocalGradients(NULL,NULL,qpt,shgval);
808 for(
int i =0;i<nshl;i++){
809 shgval_copy[i] = apf::fromVector(shgval[i+hier_off]);
810 shpval[i] = shpval_temp[i+hier_off];
811 apf::multiply(shgval_copy[i],invJ_copy,shdrv[i]);
816 apf::Vector3 vel_vect;
817 apf::Matrix3x3 grad_vel;
818 apf::getVector(velo_elem,qpt,vel_vect);
819 apf::getVectorGrad(velo_elem,qpt,grad_vel);
820 grad_vel = apf::transpose(grad_vel);
821 apf::Vector3 grad_vof;
822 apf::getGrad(vof_elem,qpt,grad_vof);
825 double pressure = apf::getScalar(pres_elem,qpt);
826 double visc_val = apf::getScalar(visc_elem,qpt);
827 apf::Vector3 grad_rho = grad_vof*(
rho_1-
rho_0);
830 getLHS(K,shdrv,
nsd,weight,visc_val,nshl);
833 getRHS(F,shpval,shdrv,vel_vect,grad_vel,
nsd,weight,nshl,visc_val,density,grad_rho,pressure,g);
839 MatAssemblyBegin(K,MAT_FINAL_ASSEMBLY);
840 MatAssemblyEnd(K,MAT_FINAL_ASSEMBLY);
847 bflux = (
double*) calloc(ndofs,
sizeof(
double));
850 for(
int s=0;
s<ndofs;
s++){
853 VecSetValues(F,ndofs,F_idx,bflux,ADD_VALUES);
854 VecAssemblyBegin(F); VecAssemblyEnd(F);
857 VecCreate(PETSC_COMM_SELF,&coef);
858 VecSetSizes(coef,ndofs,ndofs);
866 VecZeroEntries(coef);
869 KSPCreate(PETSC_COMM_SELF,&ksp);
870 KSPSetOperators(ksp,K,K);
871 KSPSetType(ksp,KSPPREONLY);
875 KSPSetFromOptions(ksp);
877 KSPSolve(ksp,F,coef);
886 KSPConvergedReason localReason;
887 KSPGetConvergedReason(ksp,&localReason);
889 nLocalSolveFailures++;
900 apf::Matrix3x3 phi_ij;
901 apf::Matrix3x3 vel_ij;
902 apf::Vector3 vel_vect;
903 apf::Vector3 grad_vof;
905 est_elem= apf::createElement(estimate,element);
906 for(
int k=0; k<numqpt;k++){
907 apf::getIntPoint(element,
int_order,k,qpt);
908 apf::getJacobian(element,qpt,J);
911 invJ = apf::transpose(invJ);
912 Jdet=fabs(apf::getJacobianDeterminant(J,
nsd));
913 weight = apf::getIntWeight(element,
int_order,k);
914 invJ_copy = apf::fromMatrix(invJ);
917 elem_shape = err_shape->getEntityShape(elem_type);
918 elem_shape->getValues(NULL,NULL,qpt,shpval_temp);
919 elem_shape->getLocalGradients(NULL,NULL,qpt,shgval);
921 for(
int i =0;i<nshl;i++){
922 shgval_copy[i] = apf::fromVector(shgval[i+hier_off]);
923 shpval[i] = shpval_temp[i+hier_off];
924 apf::multiply(shgval_copy[i],invJ_copy,shdrv[i]);
926 double visc_val = apf::getScalar(visc_elem,qpt);
927 double pres_val = apf::getScalar(pres_elem,qpt);
929 apf::getVectorGrad(est_elem,qpt,phi_ij);
930 apf::getGrad(vof_elem,qpt,grad_vof);
931 apf::getVector(velo_elem,qpt,vel_vect);
932 apf::getVectorGrad(velo_elem,qpt,vel_ij);
933 vel_ij = apf::transpose(vel_ij);
934 phi_ij = apf::transpose(phi_ij);
936 Acomp = Acomp + visc_val*
getDotProduct(phi_ij,phi_ij+apf::transpose(phi_ij))*weight;
937 Bcomp = Bcomp + apf::getDiv(velo_elem,qpt)*apf::getDiv(velo_elem,qpt)*weight;
938 visc_avg = visc_avg + visc_val*weight;
939 u_norm = u_norm + visc_val*
getDotProduct(vel_ij,vel_ij+apf::transpose(vel_ij))*weight;
942 visc_avg = visc_avg*Jdet/apf::measure(element);
943 Acomp = Acomp*Jdet/visc_avg;
945 u_norm = u_norm/visc_avg*Jdet;
946 err_est = sqrt(Acomp);
948 apf::Vector3 err_in(err_est,Acomp,Bcomp);
950 apf::setScalar(err_reg,ent,0,err_est);
951 double errRho = err_est/sqrt(apf::measure(element));
952 apf::setScalar(errRho_reg,ent,0,errRho);
956 double err_rel = err_est/sqrt(u_norm);
957 apf::setScalar(errRel_reg,ent,0,err_rel);
959 err_est_total = err_est_total+(Acomp);
960 u_norm_total = u_norm_total + u_norm;
966 apf::destroyElement(visc_elem);apf::destroyElement(pres_elem);apf::destroyElement(velo_elem);apf::destroyElement(est_elem);apf::destroyElement(vof_elem);
969 PCU_Add_Doubles(PCUObj, &err_est_total,1);
970 PCU_Add_Doubles(PCUObj, &u_norm_total,1);
972 if(nLocalSolveFailures > 0 && comm_rank==0)
973 std::cerr<<
"WARNING: "<<nLocalSolveFailures<<
" element-local error problems "
974 <<
"failed to solve (singular matrix under PREONLY+LU); their "
975 <<
"contribution to the error estimate is zero and the estimate "
976 <<
"below should not be trusted."<<std::endl;
979 u_norm_total = sqrt(u_norm_total);
983 std::cerr<<std::setprecision(10)<<std::endl;
984 std::cerr<<
"Error estimate "<<
total_error<<std::endl;
985 std::cerr<<
"Error density maximum "<<
errRho_max<<std::endl;
986 std::cerr<<
"U_norm_total "<<u_norm_total<<std::endl;
991 std::cout<<
"outputting error field\n";
993 sprintf(namebuffer,
"err_reg_%i",
nEstimate);
994 apf::writeVtkFiles(namebuffer, m);
1002 apf::destroyField(visc);
1003 apf::destroyField(estimate);
1006 std::cerr<<
"It cleared the ERM function.\n";