double ProceduralTexture::noise2(double x,double y) { double floorx=(double)((int)x);//This is kinda a cheap way to floor a double integer. double floory=(double)((int)y); double s,t,u,v;//Integer declaration s=findnoise2(floorx,floory); t=findnoise2(floorx+1,floory); u=findnoise2(floorx,floory+1);//Get the surrounding pixels to calculate the transition. v=findnoise2(floorx+1,floory+1); double int1=interpolate1(s,t,x-floorx);//Interpolate between the values. double int2=interpolate1(u,v,x-floorx);//Here we use x-floorx, to get 1st dimension. Don't mind the x-floorx thingie, it's part of the cosine formula. return interpolate1(int1,int2,y-floory);//Here we use y-floory, to get the 2nd dimension. }
void Law2_ScGeom_CapillaryPhys_Capillarity1::solver(Real suction,bool reset) { if (!scene) cerr << "scene not defined!"; shared_ptr<BodyContainer>& bodies = scene->bodies; if (dtPbased.number_of_vertices ()<1 ) triangulateData(); if (fusionDetection && !bodiesMenisciiList.initialized) bodiesMenisciiList.prepare(scene); InteractionContainer::iterator ii = scene->interactions->begin(); InteractionContainer::iterator iiEnd = scene->interactions->end(); bool hertzInitialized = false; Real i=0; for (; ii!=iiEnd ; ++ii) { i+=1; CapillaryPhys1* phys = dynamic_cast<CapillaryPhys1*>((*ii)->phys.get());//////////////////////////////////////////////////////////////////////////////////////////// if ((*ii)->isReal() && phys-> computeBridge==true) { const shared_ptr<Interaction>& interaction = *ii; if (!hertzInitialized) {//NOTE: We are assuming that only one type is used in one simulation here if (CapillaryPhys1::getClassIndexStatic()==interaction->phys->getClassIndex()) hertzOn=false; else if (MindlinCapillaryPhys::getClassIndexStatic()==interaction->phys->getClassIndex()) hertzOn=true; else LOG_ERROR("The capillary law is not implemented for interactions using"<<interaction->phys->getClassName()); } hertzInitialized = true; CapillaryPhys1* cundallContactPhysics=NULL; MindlinCapillaryPhys* mindlinContactPhysics=NULL; /// contact physics depends on the contact law, that is used (either linear model or hertz model) if (!hertzOn) cundallContactPhysics = static_cast<CapillaryPhys1*>(interaction->phys.get());//use CapillaryPhys for linear model else mindlinContactPhysics = static_cast<MindlinCapillaryPhys*>(interaction->phys.get());//use MindlinCapillaryPhys for hertz model unsigned int id1 = interaction->getId1(); unsigned int id2 = interaction->getId2(); /// interaction geometry search (this test is to compute capillarity only between spheres (probably a better way to do that) int geometryIndex1 = (*bodies)[id1]->shape->getClassIndex(); // !!! int geometryIndex2 = (*bodies)[id2]->shape->getClassIndex(); if (!(geometryIndex1 == geometryIndex2)) continue; /// definition of interacting objects (not necessarily in contact) ScGeom* currentContactGeometry = static_cast<ScGeom*>(interaction->geom.get()); /// Interacting Grains: // If you want to define a ratio between YADE sphere size and real sphere size Real alpha=1; Real R1 = alpha*std::max(currentContactGeometry->radius2,currentContactGeometry->radius1); Real R2 =alpha*std::min(currentContactGeometry->radius2,currentContactGeometry->radius1); shared_ptr<BodyContainer>& bodies = scene->bodies; Real N=bodies->size(); Real epsilon1,epsilon2; Real ran1= (N-id1+0.5)/(N+1); Real ran2= (N-id2+0.5)/(N+1); epsilon1 = epsilonMean*(2*(ran1-0.5)* disp +1);//addednow epsilon2 = epsilonMean*(2*(ran2-0.5)* disp +1); // cout << epsilon1 << "separate" <<epsilon2 <<endl; R1 = R1-epsilon1*R1; R2 =R2-epsilon2*R2; /// intergranular distance Real D = alpha*(-(currentContactGeometry->penetrationDepth))+epsilon1*R1+epsilon2*R2; if ((currentContactGeometry->penetrationDepth>=0)|| D<=0 || createDistantMeniscii) { //||(scene->iter < 1) ) // a simplified way to define meniscii everywhere if (!hertzOn) { if (fusionDetection && !cundallContactPhysics->meniscus) bodiesMenisciiList.insert((*ii)); cundallContactPhysics->meniscus=true; } else { if (fusionDetection && !mindlinContactPhysics->meniscus) bodiesMenisciiList.insert((*ii)); mindlinContactPhysics->meniscus=true; } } Real Dinterpol = D/R1; /// Suction (Capillary pressure): if (imposePressure || (!imposePressure && totalVolumeConstant)){ Real Pinterpol = 0; if (!hertzOn) Pinterpol = cundallContactPhysics->isBroken ? 0 : suction*R1/liquidTension; else Pinterpol = mindlinContactPhysics->isBroken ? 0 : suction*R1/liquidTension; if (!hertzOn) cundallContactPhysics->capillaryPressure = suction; else mindlinContactPhysics->capillaryPressure = suction; /// Capillary solution finder: if ((Pinterpol>=0) && (hertzOn? mindlinContactPhysics->meniscus : cundallContactPhysics->meniscus)) {//FIXME: need an "else {delete}" MeniscusPhysicalData solution = interpolate1(dtPbased,K::Point_3(R2/R1, Pinterpol, Dinterpol), cundallContactPhysics->m, solutions, reset); /// capillary adhesion force Real Finterpol = solution.force; Vector3r fCap = Finterpol*R1*liquidTension*currentContactGeometry->normal; if (!hertzOn) cundallContactPhysics->fCap = fCap; else mindlinContactPhysics->fCap = fCap; /// meniscus volume //FIXME: hardcoding numerical constants is bad practice generaly, and it probably reveals a flaw in that case (Bruno) Real Vinterpol = solution.volume*pow(R1,3); Real SInterface = solution.surface*pow(R1,2); if (!hertzOn) { cundallContactPhysics->vMeniscus = Vinterpol; cundallContactPhysics->SInterface = SInterface; if (Vinterpol > 0) cundallContactPhysics->meniscus = true; else cundallContactPhysics->meniscus = false; } else { mindlinContactPhysics->vMeniscus = Vinterpol; if (Vinterpol > 0) mindlinContactPhysics->meniscus = true; else mindlinContactPhysics->meniscus = false; } if (cundallContactPhysics->meniscus== false) cundallContactPhysics->SInterface=4*3.141592653589793238462643383279502884*(pow(R1,2))+4*3.141592653589793238462643383279502884*(pow(R2,2)); if (!Vinterpol) { if ((fusionDetection) || (hertzOn ? mindlinContactPhysics->isBroken : cundallContactPhysics->isBroken)) bodiesMenisciiList.remove((*ii)); /// FIXME: the following D>(...) test is wrong, should be based on penetrationDepth, and should "continue" after erasing if (D>((interactionDetectionFactor-1)*(currentContactGeometry->radius2+currentContactGeometry->radius1))) scene->interactions->requestErase(interaction); } /// wetting angles if (!hertzOn) { cundallContactPhysics->Delta1 = max(solution.delta1,solution.delta2); cundallContactPhysics->Delta2 = min(solution.delta1,solution.delta2); } else { mindlinContactPhysics->Delta1 = max(solution.delta1,solution.delta2); mindlinContactPhysics->Delta2 = min(solution.delta1,solution.delta2); } } } else{ if (cundallContactPhysics->vMeniscus==0 and cundallContactPhysics->capillaryPressure!=0){//FIXME: test capillaryPressure consistently (!0 or >0 or >=0?!) Real Pinterpol = 0; if (!hertzOn) Pinterpol = cundallContactPhysics->isBroken ? 0 : cundallContactPhysics->capillaryPressure*R1/liquidTension; else Pinterpol = mindlinContactPhysics->isBroken ? 0 : cundallContactPhysics->capillaryPressure*R1/liquidTension; // if (!hertzOn) cundallContactPhysics->capillaryPressure = suction; // else mindlinContactPhysics->capillaryPressure = suction; /// Capillary solution finder: if ((Pinterpol>=0) && (hertzOn? mindlinContactPhysics->meniscus : cundallContactPhysics->meniscus)) { MeniscusPhysicalData solution = interpolate1(dtPbased,K::Point_3(R2/R1, Pinterpol, Dinterpol), cundallContactPhysics->m, solutions, reset); /// capillary adhesion force Real Finterpol = solution.force; Vector3r fCap = Finterpol*R1*liquidTension*currentContactGeometry->normal; if (!hertzOn) cundallContactPhysics->fCap = fCap; else mindlinContactPhysics->fCap = fCap; /// meniscus volume //FIXME: hardcoding numerical constants is bad practice generaly, and it probably reveals a flaw in that case (Bruno) Real Vinterpol = solution.volume*pow(R1,3); Real SInterface = solution.surface*pow(R1,2); if (!hertzOn) { cundallContactPhysics->vMeniscus = Vinterpol; cundallContactPhysics->SInterface = SInterface; if (Vinterpol > 0) cundallContactPhysics->meniscus = true; else cundallContactPhysics->meniscus = false; } else { mindlinContactPhysics->vMeniscus = Vinterpol; if (Vinterpol > 0) mindlinContactPhysics->meniscus = true; else mindlinContactPhysics->meniscus = false; } if (cundallContactPhysics->meniscus== false) cundallContactPhysics->SInterface=4*3.141592653589793238462643383279502884*(pow(R1,2))+4*3.141592653589793238462643383279502884*(pow(R2,2)); if (!Vinterpol) { if ((fusionDetection) || (hertzOn ? mindlinContactPhysics->isBroken : cundallContactPhysics->isBroken)) bodiesMenisciiList.remove((*ii)); if (D>((interactionDetectionFactor-1)*(currentContactGeometry->radius2+currentContactGeometry->radius1))) scene->interactions->requestErase(interaction); } /// wetting angles if (!hertzOn) { cundallContactPhysics->Delta1 = max(solution.delta1,solution.delta2); cundallContactPhysics->Delta2 = min(solution.delta1,solution.delta2); } else { mindlinContactPhysics->Delta1 = max(solution.delta1,solution.delta2); mindlinContactPhysics->Delta2 = min(solution.delta1,solution.delta2); } } } else{ Real Vinterpol = 0; if (!hertzOn) { Vinterpol = cundallContactPhysics->vMeniscus/pow(R1,3); } else Vinterpol = mindlinContactPhysics->vMeniscus; /// Capillary solution finder: if ((hertzOn? mindlinContactPhysics->meniscus : cundallContactPhysics->meniscus)) { MeniscusPhysicalData solution = interpolate2(dtVbased,K::Point_3(R2/R1, Vinterpol, Dinterpol), cundallContactPhysics->m, solutions,reset); /// capillary adhesion force Real Finterpol = solution.force; Vector3r fCap = Finterpol*R1*liquidTension*currentContactGeometry->normal; if (!hertzOn) cundallContactPhysics->fCap = fCap; else mindlinContactPhysics->fCap = fCap; /// suction and interfacial area Real Pinterpol = solution.succion*liquidTension/R1; Real SInterface = solution.surface*pow(R1,2); if (!hertzOn) { cundallContactPhysics->capillaryPressure = Pinterpol; cundallContactPhysics->SInterface = SInterface; if (Finterpol > 0) cundallContactPhysics->meniscus = true; else{ cundallContactPhysics->vMeniscus=0; cundallContactPhysics->meniscus = false; } } else { mindlinContactPhysics->capillaryPressure = Pinterpol; if (Finterpol > 0) mindlinContactPhysics->meniscus = true; else { cundallContactPhysics->vMeniscus=0; mindlinContactPhysics->meniscus = false; } } if (!Vinterpol) { if ((fusionDetection) || (hertzOn ? mindlinContactPhysics->isBroken : cundallContactPhysics->isBroken)) bodiesMenisciiList.remove((*ii)); if (D>((interactionDetectionFactor-1)*(currentContactGeometry->radius2+currentContactGeometry->radius1))) scene->interactions->requestErase(interaction); } /// wetting angles if (!hertzOn) { cundallContactPhysics->Delta1 = max(solution.delta1,solution.delta2); cundallContactPhysics->Delta2 = min(solution.delta1,solution.delta2); } else { mindlinContactPhysics->Delta1 = max(solution.delta1,solution.delta2); mindlinContactPhysics->Delta2 = min(solution.delta1,solution.delta2); } } } } ///interaction is not real //If the interaction is not real, it should not be in the list } else if (fusionDetection) bodiesMenisciiList.remove((*ii)); } if (fusionDetection) checkFusion(); }