/* Assuming this cond func is called in the Element IC to assign spatially varying amaterial_I. Make this a template for other situations. */ void _SnacCondFunc_AssignPhaseID( Index element_lI, Variable_Index var_I, void* _context, void* result ){ Snac_Context* context = (Snac_Context*)_context; Snac_Element* element = Snac_Element_At( context, element_lI ); Material_Index* material_I = (Material_Index*)result; /* Stuff for convenience */ Mesh* mesh = context->mesh; MeshLayout* layout = (MeshLayout*)mesh->layout; HexaMD* decomp = (HexaMD*)layout->decomp; IJK ijk; Element_GlobalIndex element_gI = _MeshDecomp_Element_LocalToGlobal1D( decomp, element_lI ); Index oneThird = (unsigned int)((11.0/30.0)*decomp->elementGlobal3DCounts[0]); Index twoThirds = (unsigned int)((19.0/30.0)*decomp->elementGlobal3DCounts[0]); RegularMeshUtils_Element_1DTo3D( decomp, element_gI, &ijk[0], &ijk[1], &ijk[2] ); fprintf(stderr,"Running %s\n",__func__); if( ijk[0] < oneThird ) (*material_I) = 0; else if( ijk[0] >= oneThird && ijk[0] <= twoThirds ) (*material_I) = 1; else (*material_I) = 0; }
PetscErrorCode KSPBuildPressure_CB_Nullspace_BSSCR(KSP ksp) { KSP_BSSCR *bsscr = (KSP_BSSCR *)ksp->data; FeEquationNumber *eq_num = bsscr->solver->st_sle->pSolnVec->feVariable->eqNum; FeMesh *feMesh = bsscr->solver->st_sle->pSolnVec->feVariable->feMesh; /* is the pressure mesh */ unsigned ijk[3]; Vec t, v; int numLocalNodes, globalNodeNumber, i, j, eq; MatStokesBlockScaling BA = bsscr->BA; PetscErrorCode ierr; Mat Amat,Pmat, G; MatStructure pflag; PetscFunctionBegin; /* get G matrix from Amat matrix operator on ksp */ ierr=Stg_PCGetOperators(ksp->pc,&Amat,&Pmat,&pflag);CHKERRQ(ierr); MatNestGetSubMat( Amat, 0,1, &G );/* G should always exist */ /* now create Vecs t and v to match size of G: i.e. pressure */ /* NOTE: not using "h" vector from ksp->vec_rhs because this part of the block vector doesn't always exist */ MatGetVecs( G, &t, PETSC_NULL );/* t and v are destroyed in KSPDestroy_BSSCR */ MatGetVecs( G, &v, PETSC_NULL );/* t and v such that can do G*t */ numLocalNodes = Mesh_GetLocalSize( feMesh, MT_VERTEX); /* number of nodes on current proc not counting any shadow nodes */ for(j=0;j<numLocalNodes;j++){ i = globalNodeNumber = Mesh_DomainToGlobal( feMesh, MT_VERTEX, j); RegularMeshUtils_Element_1DTo3D(feMesh, i, ijk); eq = eq_num->destinationArray[j][0];/* get global equation number -- 2nd arg is always 0 because pressure has only one dof */ if(eq != -1){ if( (ijk[0]+ijk[1]+ijk[2])%2 ==0 ){ VecSetValue(t,eq,1.0,INSERT_VALUES); } else{ VecSetValue(v,eq,1.0,INSERT_VALUES); }}} VecAssemblyBegin( t ); VecAssemblyEnd( t ); VecAssemblyBegin( v ); VecAssemblyEnd( v ); /* Scaling the null vectors here because it easier at the moment *//* maybe should do this in the original scaling function */ if( BA->scaling_exists == PETSC_TRUE ){ Vec R2; /* Get the scalings out the block mat data */ VecNestGetSubVec( BA->Rz, 1, &R2 ); VecPointwiseDivide( t, t, R2); /* x <- x * 1/R2 */ VecPointwiseDivide( v, v, R2); } bsscr_writeVec( t, "t", "Writing t vector"); bsscr_writeVec( v, "v", "Writing v vector"); bsscr->t=t; bsscr->v=v; PetscFunctionReturn(0); }
void _SnacCondFunc_DeadSea( Index element_lI, Variable_Index var_I, void* _context, void* result ){ Snac_Context* context = (Snac_Context*)_context; Snac_Element* element = Snac_Element_At( context, element_lI ); Material_Index* material_I = (Material_Index*)result; /* Stuff for convenience */ Mesh* mesh = context->mesh; MeshLayout* layout = (MeshLayout*)mesh->layout; HexaMD* decomp = (HexaMD*)layout->decomp; IJK ijk; Element_GlobalIndex global_I_range = decomp->elementGlobal3DCounts[0]; Element_GlobalIndex global_K_range = decomp->elementGlobal3DCounts[2]; Element_GlobalIndex element_gI = _MeshDecomp_Element_LocalToGlobal1D( decomp, element_lI ); unsigned int matID=0, tetra_I; RegularMeshUtils_Element_1DTo3D( decomp, element_gI, &ijk[0], &ijk[1], &ijk[2] ); if( (ijk[0] < (global_I_range-ijk[2])) && (ijk[2] < global_K_range/4) ) matID=1; if((ijk[0]==(global_I_range-ijk[2]-1)) && (ijk[2] < (global_K_range/4)) ) matID=2; if( (ijk[0]==global_I_range/2) && (ijk[2]>=global_K_range/4) ) matID=2; if( ((ijk[0]>=global_I_range/2)&&(ijk[0]<=global_I_range*3/4)) && (ijk[2]==global_K_range/4) ) matID=2; (*material_I)=matID; for( tetra_I = 0; tetra_I < Tetrahedra_Count; tetra_I++ ) { element->tetra[tetra_I].material_I=matID; } }
void SnacViscoPlastic_Constitutive( void* _context, Element_LocalIndex element_lI ) { Snac_Context* context = (Snac_Context*)_context; Snac_Element* element = Snac_Element_At( context, element_lI ); SnacViscoPlastic_Element* viscoplasticElement = ExtensionManager_Get( context->mesh->elementExtensionMgr, element, SnacViscoPlastic_ElementHandle ); SnacTemperature_Element* temperatureElement = ExtensionManager_Get( context->mesh->elementExtensionMgr, element, SnacTemperature_ElementHandle ); const Snac_Material* material = &context->materialProperty[element->material_I]; /*ccccc*/ MeshLayout* meshLayout = (MeshLayout*)context->meshLayout; HexaMD* decomp = (HexaMD*)meshLayout->decomp; IJK ijk; Element_GlobalIndex element_gI = _MeshDecomp_Element_LocalToGlobal1D( decomp, element_lI ); EntryPoint* temperatureEP; RegularMeshUtils_Element_1DTo3D( decomp, element_gI, &ijk[0], &ijk[1], &ijk[2] ); /*ccccc*/ temperatureEP = Context_GetEntryPoint( context, "Snac_EP_LoopElementsEnergy" ); /* If this is a ViscoPlastic material, calculate its stress. */ if ( material->rheology & Snac_Material_ViscoPlastic ) { Tetrahedra_Index tetra_I; Node_LocalIndex node_lI; /* viscoplastic material properties */ const double bulkm = material->lambda + 2.0f * material->mu/3.0f; StressTensor* stress; StrainTensor* strain; Strain plasticStrain; double* viscosity; double straind0,straind1,straind2,stressd0,stressd1,stressd2; double Stress0[3][3]; double trace_strain; double trace_stress; double temp; double vic1; double vic2; double VolumicStress; double rviscosity=material->refvisc; double rmu= material->mu; double srJ2; double avgTemp; plModel yieldcriterion=material->yieldcriterion; /* For now reference values of viscosity, second invariant of deviatoric */ /* strain rate and reference temperature are being hard wired ( these specific */ /* values are from paper by Hall et. al., EPSL, 2003 */ double rstrainrate = material->refsrate; double rTemp = material->reftemp; double H = material->activationE; // kJ/mol double srexponent = material->srexponent; double srexponent1 = material->srexponent1; double srexponent2 = material->srexponent2; const double R=8.31448; // J/mol/K /* elasto-plastic material properties */ double cohesion = 0.0f; double frictionAngle = 0.0f; double dilationAngle = 0.0f; double hardening = 0.0f; double tension_cutoff=0.0; const double degrad = PI / 180.0f; double totalVolume=0.0f,depls=0.0f; unsigned int i; double tmp=0.0; const double a1 = material->lambda + 2.0f * material->mu ; const double a2 = material->lambda ; int ind=0; int principal_stresses(StressTensor* stress,double sp[],double cn[3][3]); int principal_stresses_orig(StressTensor* stress, double sp[3], double cn[3][3]); /* printf("Entered ViscoPlastic update \n"); */ /* Work out the plastic material properties of this element */ for( tetra_I = 0; tetra_I < Tetrahedra_Count; tetra_I++ ) { double cn[3][3] = {{0.0,0.0,0.0},{0.0,0.0,0.0},{0.0,0.0,0.0}}; double s[3] = {0.0,0.0,0.0}; double alam, dep1, dep2, dep3, depm; /*ccccc*/ stress = &element->tetra[tetra_I].stress; strain = &element->tetra[tetra_I].strain; plasticStrain = viscoplasticElement->plasticStrain[tetra_I]; viscosity = &viscoplasticElement->viscosity[tetra_I]; if( context->computeThermalStress ) { (*stress)[0][0] += temperatureElement->thermalStress[tetra_I]; (*stress)[1][1] += temperatureElement->thermalStress[tetra_I]; (*stress)[2][2] += temperatureElement->thermalStress[tetra_I]; } /* storing original stress in local array */ Stress0[0][0] = (*stress)[0][0]; Stress0[1][1] = (*stress)[1][1]; Stress0[2][2] = (*stress)[2][2]; Stress0[0][1] = (*stress)[0][1]; Stress0[0][2] = (*stress)[0][2]; Stress0[1][2] = (*stress)[1][2]; trace_stress = (*stress)[0][0] + (*stress)[1][1] + (*stress)[2][2]; /* trace_strain = element->tetra[tetra_I].volume/element->tetra[tetra_I].old_volume-1.0f; */ trace_strain = (*strain)[0][0] + (*strain)[1][1] + (*strain)[2][2]; /* printf(" Trace strain=%g\t Trace Stress=%g\n",trace_strain,trace_stress); */ /* Deviatoric Stresses and Strains */ straind0 = (*strain)[0][0] - (trace_strain) / 3.0f; straind1 = (*strain)[1][1] - (trace_strain) / 3.0f; straind2 = (*strain)[2][2] - (trace_strain) / 3.0f; stressd0 = (*stress)[0][0] - (trace_stress) / 3.0f; stressd1 = (*stress)[1][1] - (trace_stress) / 3.0f; stressd2 = (*stress)[2][2] - (trace_stress) / 3.0f; /* compute viscosity and add thermal stress */ if( temperatureEP ) { srJ2 = sqrt(fabs(straind1*straind2+straind2*straind0+straind0*straind1 -(*strain[0][1])*(*strain[0][1])-(*strain[0][2])*(*strain[0][2])-(*strain[1][2])*(*strain[1][2])))/context->dt; if(srJ2 == 0.0f) srJ2 = rstrainrate; // temporary. should be vmax/length_scale avgTemp=0.0; for(node_lI=0; node_lI<4; node_lI++) { Snac_Node* contributingNode = Snac_Element_Node_P( context, element_lI, TetraToNode[tetra_I][node_lI] ); SnacTemperature_Node* temperatureNodeExt = ExtensionManager_Get( context->mesh->nodeExtensionMgr,contributingNode, SnacTemperature_NodeHandle ); avgTemp += 0.25 * temperatureNodeExt->temperature; assert( !isnan(avgTemp) && !isinf(avgTemp) ); } // Hall et. al., 2004, G3 (*viscosity)= rviscosity*pow((srJ2/rstrainrate),(1./srexponent-1.)) *exp(H/R*(1./(avgTemp+273.15)-1./(rTemp+273.15))); if((*viscosity) < material->vis_min) (*viscosity) = material->vis_min; if((*viscosity) > material->vis_max) (*viscosity) = material->vis_max; Journal_Firewall( !isnan((*viscosity)) && !isinf((*viscosity)), context->snacError, "rvisc=%e Erattio=%e pow(E)=%e, dT=%e exp=%e\n", rviscosity, (srJ2/rstrainrate), pow((srJ2/rstrainrate), (1./srexponent-1.)), exp(H/R*(1./(avgTemp+273.15)-1./(rTemp+273.15))), (1./(avgTemp+273.15)-1./(rTemp+273.15)) ); #if 0 // Lavier and Buck, JGR, 2002 (*viscosity) = pow(rviscosity,-1.0/srexponent1)*pow(srJ2,1.0/srexponent2-1)*exp(H/R/(avgTemp+273.15)); #endif } else { (*viscosity) = rviscosity; Journal_Firewall( !isnan((*viscosity)) && !isinf((*viscosity)), context->snacError, "(*viscosity) is nan or inf\n" ); } /* Non dimensional parameters elastic/viscous */ temp = rmu / (2.0f* (*viscosity)) * context->dt; vic1 = 1.0f - temp; vic2 = 1.0f / (1.0f + temp); /* printf("temp=%g\t rmu=%g\t viscosity=%g\t\n",temp,rmu,*viscosity); */ /* printf("trace_stress=%g\t trace_strain=%g\t vic1=%g\t vic2=%g\n",trace_stress,trace_strain,vic1,vic2); */ /* Deviatoric Stress Update */ stressd0 = (stressd0 * vic1 + 2.0f * rmu * straind0) * vic2 ; stressd1 = (stressd1 * vic1 + 2.0f * rmu * straind1) * vic2 ; stressd2 = (stressd2 * vic1 + 2.0f * rmu * straind2) * vic2 ; (*stress)[0][1] =((*stress)[0][1] * vic1 + 2.0f * rmu * (*strain)[0][1]) * vic2; (*stress)[0][2] =((*stress)[0][2] * vic1 + 2.0f * rmu * (*strain)[0][2]) * vic2; (*stress)[1][2] =((*stress)[1][2] * vic1 + 2.0f * rmu * (*strain)[1][2]) * vic2; /* Isotropic stress is elastic, WARNING:volumic Strain may be better defined as volumique change in the mesh */ VolumicStress = trace_stress / 3.0f + bulkm * trace_strain; (*stress)[0][0] = stressd0 + VolumicStress; (*stress)[1][1] = stressd1 + VolumicStress; (*stress)[2][2] = stressd2 + VolumicStress; principal_stresses(stress,s,cn); /* compute friction and dilation angles based on accumulated plastic strain in tetrahedra */ /* Piece-wise linear softening */ /* Find current properties from linear interpolation */ #if 0 /*ccccc*/ if(material->putSeeds && context->loop <= 1) { if(ijk[1] >= decomp->elementGlobal3DCounts[1]-2) if(ijk[0] == decomp->elementGlobal3DCounts[0]/2 ) { //if(ijk[0] >= 10 && ijk[0] <= 14 ) { viscoplasticElement->plasticStrain[tetra_I] = 1.1*material->plstrain[1]; plasticStrain = viscoplasticElement->plasticStrain[tetra_I]; fprintf(stderr,"loop=%d ijk=%d %d %d aps=%e plasticE=%e\n", context->loop,ijk[0],ijk[1],ijk[2],plasticStrain, viscoplasticElement->plasticStrain[tetra_I]); } } /*ccccc*/ #endif for( i = 0; i < material->nsegments; i++ ) { const double pl1 = material->plstrain[i]; const double pl2 = material->plstrain[i+1]; if( plasticStrain >= pl1 && plasticStrain <= pl2 ) { const double tgf = (material->frictionAngle[i+1] - material->frictionAngle[i]) / (pl2 - pl1); const double tgd = (material->dilationAngle[i+1] - material->dilationAngle[i]) / (pl2 - pl1); const double tgc = (material->cohesion[i+1] - material->cohesion[i]) / (pl2 - pl1); frictionAngle = material->frictionAngle[i] + tgf * (plasticStrain - pl1); dilationAngle = material->dilationAngle[i] + tgd * (plasticStrain - pl1); cohesion = material->cohesion[i] + tgc * (plasticStrain - pl1); hardening = tgc; } } if( frictionAngle > 0.0f ) { tension_cutoff = material->ten_off; if( frictionAngle > 0.0) { tmp = cohesion / tan( frictionAngle * degrad); if(tmp < tension_cutoff) tension_cutoff=tmp; } } else { if( plasticStrain < 0.0 ) { viscoplasticElement->plasticStrain[tetra_I] = 0.0; plasticStrain = viscoplasticElement->plasticStrain[tetra_I]; fprintf(stderr,"Warning: negative plastic strain. Setting to zero, but check if remesher is on and this happended for an external tet. rank:%d elem:%d tet:%d plasticStrain=%e frictionAngle=%e\n",context->rank,element_lI,tetra_I,plasticStrain,frictionAngle); frictionAngle = material->frictionAngle[0]; dilationAngle = material->dilationAngle[0]; cohesion = material->cohesion[0]; } else { /* frictionAngle < 0.0 violates second law of thermodynamics */ fprintf(stderr,"Error due to an unknown reason: rank:%d elem:%d tet:%d plasticStrain=%e frictionAngle=%e\n",context->rank,element_lI,tetra_I,plasticStrain,frictionAngle); assert(0); } } if( yieldcriterion == mohrcoulomb ) { double sphi = sin( frictionAngle * degrad ); double spsi = sin( dilationAngle * degrad ); double anphi = (1.0f + sphi) / (1.0f - sphi); double anpsi = (1.0f + spsi) / (1.0f - spsi); double fs = s[0] - s[2] * anphi + 2 * cohesion * sqrt( anphi ); double ft = s[2] - tension_cutoff; /* CHECK FOR COMPOSITE YIELD CRITERION */ ind=0; if( fs < 0.0f || ft > 0.0f ) { /*! Failure: shear or tensile */ double aP = sqrt( 1.0f + anphi * anphi ) + anphi; double sP = tension_cutoff * anphi - 2 * cohesion * sqrt( anphi ); double h = s[2] - tension_cutoff + aP * ( s[0] - sP ); ind=1; if( h < 0.0f ) { /* !shear failure */ alam = fs / ( a1 - a2 * anpsi + a1 * anphi * anpsi - a2 * anphi + 2.0*sqrt(anphi)*hardening ); s[0] -= alam * ( a1 - a2 * anpsi ); s[1] -= alam * a2 * ( 1.0f - anpsi ); s[2] -= alam * ( a2 - a1 * anpsi ); dep1 = alam; dep2 = 0.0f; dep3 = -alam * anpsi; } else { /* tensile failure */ alam = ft / a1; s[0] -= alam * a2; s[1] -= alam * a2; s[2] -= alam * a1; dep1 = 0.0f; dep2 = 0.0f; dep3 = alam; } } else { /* ! no failure - just elastic increment */ dep1 = 0.0f; dep2 = 0.0f; dep3 = 0.0f; } if(ind) { unsigned int k,m,n; /* Second invariant of accumulated plastic increment */ depm = ( dep1 + dep2 + dep3 ) / 3.0f; viscoplasticElement->plasticStrain[tetra_I] += sqrt( 0.5f * ((dep1-depm) * (dep1-depm) + (dep2-depm) * (dep2-depm) + (dep3-depm) * (dep3-depm) + depm*depm) ); /* Stress projection back to euclidean coordinates */ memset( stress, 0, sizeof((*stress)) ); /* Resolve back to global axes */ for( m = 0; m < 3; m++ ) { for( n = m; n < 3; n++ ) { for( k = 0; k < 3; k++ ) { /* (*stress)[m][n] += cn[k][m] * cn[k][n] * s[k]; */ (*stress)[m][n] += cn[m][k] * cn[n][k] * s[k]; } } } } } else Journal_Firewall( (0>1), "In %s: \"mohrcoulomb\" is the only available yield criterion.\n", __func__ ); /* linear healing: applied whether this tet has yielded or not. Parameters are hardwired for now, but should be given through an input file. */ /* viscoplasticElement->plasticStrain[tetra_I] *= (1.0/(1.0+context->dt/1.0e+12)); */ viscoplasticElement->plasticStrain[tetra_I] *= (1.0/(1.0+context->dt/(ind?1.0e+13:5.0e+11))); depls += viscoplasticElement->plasticStrain[tetra_I]*element->tetra[tetra_I].volume; totalVolume += element->tetra[tetra_I].volume; } /* volume-averaged accumulated plastic strain, aps */ viscoplasticElement->aps = depls/totalVolume; } }
double _GALEDruckerPrager_GetYieldCriterion( void* druckerPrager, ConstitutiveMatrix* constitutiveMatrix, MaterialPointsSwarm* materialPointsSwarm, Element_LocalIndex lElement_I, MaterialPoint* materialPoint, Coord xi ) { GALEDruckerPrager* self = (GALEDruckerPrager*) druckerPrager; Dimension_Index dim = constitutiveMatrix->dim; double cohesion; double cohesionAfterSoftening; double frictionCoefficient; double frictionCoefficientAfterSoftening; double minimumYieldStress; double minimumViscosity; double effectiveCohesion; double effectiveFrictionCoefficient; double frictionalStrength; double pressure; GALEDruckerPrager_Particle* particleExt; Cell_Index cell_I; Coord coord; Element_GlobalIndex element_gI = 0; unsigned inds[3]; Grid* elGrid; Bool inside_boundary; double factor; /* Get Parameters From Rheology */ cohesion = self->cohesion; cohesionAfterSoftening = self->cohesionAfterSoftening; frictionCoefficient = self->frictionCoefficient; frictionCoefficientAfterSoftening = self->frictionCoefficientAfterSoftening; minimumYieldStress = self->minimumYieldStress; minimumViscosity = self->minimumViscosity; particleExt = (GALEDruckerPrager_Particle*)ExtensionManager_Get( materialPointsSwarm->particleExtensionMgr, materialPoint, self->particleExtHandle ); if( self->pressureField ) FeVariable_InterpolateWithinElement( self->pressureField, lElement_I, xi, &pressure ); else { SwarmVariable_ValueAt( self->swarmPressure, constitutiveMatrix->currentParticleIndex, &pressure ); } cell_I=CellLayout_MapElementIdToCellId(materialPointsSwarm->cellLayout, lElement_I ); FeMesh_CoordLocalToGlobal(self->pressureField->feMesh, cell_I, xi, coord); if(self->hydrostaticTerm) { pressure+=HydrostaticTerm_Pressure(self->hydrostaticTerm,coord); } /* Normally we add the average of the trace of the stress. With compressible material, you have to do it. But with stabilized linear pressure elements, the non-zero trace is a numerical artifact. So we do not add it. */ /* pressure+=self->trace/dim; */ /* Calculate frictional strength. We modify the friction and cohesion because we have grouped terms from the normal stresses and moved it to the yield indicator. */ /* Big song and dance to see if we are at a boundary that we care about */ elGrid = *(Grid**)ExtensionManager_Get(self->pressureField->feMesh->info, self->pressureField->feMesh, self->pressureField->feMesh->elGridId ); element_gI = FeMesh_ElementDomainToGlobal( self->pressureField->feMesh, lElement_I ); RegularMeshUtils_Element_1DTo3D( self->pressureField->feMesh, element_gI, inds ); inside_boundary=(self->boundaryBottom && inds[1]==0) || (self->boundaryTop && inds[1]==elGrid->sizes[1]-1) || (self->boundaryLeft && inds[0]==0) || (self->boundaryRight && inds[0]==elGrid->sizes[0]-1) || (dim==3 && ((self->boundaryBack && inds[2]==0) || (self->boundaryFront && inds[2]==elGrid->sizes[2]-1))); effectiveFrictionCoefficient = _GALEDruckerPrager_EffectiveFrictionCoefficient( self, materialPoint, inside_boundary ); effectiveCohesion = _GALEDruckerPrager_EffectiveCohesion(self,materialPoint, inside_boundary); if(dim==2) { /* effectiveFrictionCoefficient=tan(phi). If factor=sin(atan(1/tan(phi))) => factor=cos(phi)=1/sqrt(1+tan(phi)**2) */ factor=1/sqrt(1 + effectiveFrictionCoefficient*effectiveFrictionCoefficient); frictionalStrength = effectiveFrictionCoefficient*pressure*factor + effectiveCohesion*factor; } else { double cos_phi, sin_phi; /* cos(phi)=1/sqrt(1+tan(phi)**2) */ cos_phi= 1/sqrt(1 + effectiveFrictionCoefficient*effectiveFrictionCoefficient); sin_phi=effectiveFrictionCoefficient*cos_phi; factor=2*cos_phi/(sqrt(3.0)*(3-sin_phi)); /* The full expression is sqrt(J2)=p*2*sin(phi)/(sqrt(3)*(3-sin(phi))) + C*6*cos(phi)/(sqrt(3)*(3-sin(phi))) Note the extra factor of 3 for cohesion */ frictionalStrength = effectiveFrictionCoefficient*factor*pressure + effectiveCohesion*3*factor; } /* If the minimumYieldStress is not set, then use the effective cohesion. Maybe it should be the modified effective cohesion, though that probably should not matter much. */ minimumYieldStress = self->minimumYieldStress; if(minimumYieldStress==0.0) minimumYieldStress=effectiveCohesion; /* Make sure frictionalStrength is above the minimum */ if ( frictionalStrength < minimumYieldStress*factor) frictionalStrength = minimumYieldStress*factor; self->yieldCriterion = frictionalStrength; self->curFrictionCoef = effectiveFrictionCoefficient*factor; return frictionalStrength; }
void Spherical_CubedSphereNusselt_Output( UnderworldContext* context ) { Spherical_CubedSphereNusselt* self = NULL; Swarm* swarm = NULL; FeMesh* mesh = NULL; ElementType* elementType = NULL; Grid* grid = NULL; double avgT, vol; self = (Spherical_CubedSphereNusselt*)LiveComponentRegister_Get( context->CF->LCRegister, (Name)Spherical_CubedSphereNusselt_Type ); FeVariable *temperatureGradientsField = self->temperatureGradientsField; FeVariable *temperatureField = self->temperatureField; FeVariable *velocityField = self->velocityField; swarm = self->gaussSwarm; mesh = (FeMesh*)self->mesh; assert( self ); assert( mesh ); assert( swarm ); /* for each boundary element at the top integrate dT/dr & integrate T*v_r ASSUMPTIONS: * uses grid data structure for r,theta mesh (cartesian topology so i can) */ unsigned nEls, e_i, cell_i, nPoints, p_i, ijk[3]; IntegrationPoint* particle; double value[3], xyz[3], rtp[3], detJac, dT_dr, factor, vel[3], T, vel_rtp[3]; double gVolume[2], volume[2]; double J_Nu[2], gJ_Nu[2]; double rMin = ((RSGenerator*)mesh->generator)->crdMin[0]; double rMax = ((RSGenerator*)mesh->generator)->crdMin[1]; double dxdr[3], r; elementType = FeMesh_GetElementType( mesh, 0 ); // assuming all element are the same as el 0 memset( J_Nu, 0, 2*sizeof(double) ); memset( volume, 0, 2*sizeof(double) ); RegularMeshUtils_ErrorCheckAndGetDetails( (Mesh*)mesh, MT_VOLUME, &nEls, &grid ); for( e_i = 0; e_i < nEls; e_i++ ) { // use cartesian grid data structure - can improve later on to make more general RegularMeshUtils_Element_1DTo3D( mesh, Mesh_DomainToGlobal( (Mesh*)mesh, MT_VOLUME, e_i ), ijk ); // if element is on the outer radius boundary if( ijk[0] == grid->sizes[0] - 1 ) { // get integration number of integration points in cell cell_i = CellLayout_MapElementIdToCellId( swarm->cellLayout, e_i ); nPoints = swarm->cellParticleCountTbl[ cell_i ]; for( p_i = 0; p_i < nPoints; p_i++ ) { // get integration particle particle = (IntegrationPoint*) Swarm_ParticleInCellAt( swarm, cell_i, p_i ); // get temperatureDeriv and xyz FeVariable_InterpolateFromMeshLocalCoord( temperatureField, (FeMesh*)mesh, e_i, particle->xi, &T); FeVariable_InterpolateFromMeshLocalCoord( velocityField, (FeMesh*)mesh, e_i, particle->xi, vel); FeVariable_InterpolateFromMeshLocalCoord( temperatureGradientsField, (FeMesh*)mesh, e_i, particle->xi, value); FeMesh_CoordLocalToGlobal( mesh, e_i, particle->xi, xyz ); Spherical_XYZ2regionalSphere( xyz, rtp ); Spherical_VectorXYZ2regionalSphere( vel, xyz, vel_rtp ); detJac = ElementType_JacobianDeterminant( elementType, (FeMesh*)mesh, e_i, particle->xi, 3 ); r = sqrt( rtp[0]*rtp[0] + rtp[1]*rtp[1] + rtp[2]*rtp[2] ); dxdr[0] = r/xyz[0]; dxdr[1] = r/xyz[1]; dxdr[2] = r/xyz[2]; // calc dT_dr = dT_dx * dx_dr + dT_dy * dy_dr + dT_dz * dz_dr dT_dr = value[0]*dxdr[0] + value[1]*dxdr[1] + value[2]*dxdr[2]; // add to element integral J_Nu[0] += particle->weight * detJac * (dT_dr - T*vel_rtp[0]); volume[0] += detJac * particle->weight; } } // if element is on the inner radius boundary if( ijk[0] == 0 ) { // get integration number of integration points in cell cell_i = CellLayout_MapElementIdToCellId( swarm->cellLayout, e_i ); nPoints = swarm->cellParticleCountTbl[ cell_i ]; for( p_i = 0; p_i < nPoints; p_i++ ) { // get integration particle particle = (IntegrationPoint*) Swarm_ParticleInCellAt( swarm, cell_i, p_i ); // get temperatureDeriv and xyz FeVariable_InterpolateFromMeshLocalCoord( temperatureField, (FeMesh*)mesh, e_i, particle->xi, &T); FeVariable_InterpolateFromMeshLocalCoord( velocityField, (FeMesh*)mesh, e_i, particle->xi, vel); FeVariable_InterpolateFromMeshLocalCoord( temperatureGradientsField, (FeMesh*)mesh, e_i, particle->xi, value); FeMesh_CoordLocalToGlobal( mesh, e_i, particle->xi, xyz ); Spherical_XYZ2regionalSphere( xyz, rtp ); Spherical_VectorXYZ2regionalSphere( vel, xyz, vel_rtp ); detJac = ElementType_JacobianDeterminant( elementType, (FeMesh*)mesh, e_i, particle->xi, 3 ); r = sqrt( rtp[0]*rtp[0] + rtp[1]*rtp[1] + rtp[2]*rtp[2] ); dxdr[0] = r/xyz[0]; dxdr[1] = r/xyz[1]; dxdr[2] = r/xyz[2]; // calc dT_dr = dT_dx * dx_dr + dT_dy * dy_dr + dT_dz * dz_dr dT_dr = value[0]*dxdr[0] + value[1]*dxdr[1] + value[2]*dxdr[2]; J_Nu[1] += particle->weight * detJac * (dT_dr - T*vel_rtp[0]); volume[1] += detJac * particle->weight; } } } /* Sum of procs integral */ (void)MPI_Allreduce( J_Nu, gJ_Nu, 2, MPI_DOUBLE, MPI_SUM, context->communicator ); (void)MPI_Allreduce( volume, gVolume, 2, MPI_DOUBLE, MPI_SUM, context->communicator ); // to get horizontally averaged quantities we divide by volume gJ_Nu[0] /= gVolume[0]; gJ_Nu[1] /= gVolume[1]; // normalise CubedSphereNusselt upper condition - this is for scaling against published results // 1.22 and 2.22 are the inner and outer radii for those results factor = rMax * log(0.55); gJ_Nu[0] = factor * gJ_Nu[0]; // normalise CubedSphereNusselt lower condition factor = rMin * log(0.55); gJ_Nu[1] = factor * gJ_Nu[1]; avgT = PpcIntegral_Integrate( self->volAvgT ); vol = PpcIntegral_Integrate( self->vol ); StgFEM_FrequentOutput_PrintValue( context, avgT/vol ); StgFEM_FrequentOutput_PrintValue( context, gJ_Nu[0] ); StgFEM_FrequentOutput_PrintValue( context, gJ_Nu[1] ); }