qreal XYSPline::interpolate(qreal x) { if (m_points.size() <= 1) return 0.0; switch (m_type) { case Spline: #ifndef NOGSLLIB if (m_points.size() == 2) { return interpolate2(x); } else { return interpolateS(x); } #else qDebug("Spline not supported: recompile xygraph without the NOGSLLIB define."); #endif case Linear: return interpolate2(x); // case Polynomial: // if (m_points.size() <= 3) // return interpolate2(x); // else // return interpolate4(x); } return 0.0; }
double REACTION_KEQ::calculate_logKeq(double T, double n_mix) { double a1 = interpolate2 (n, A1, num_data, n_mix); double a2 = interpolate2 (n, A2, num_data, n_mix); double a3 = interpolate2 (n, A3, num_data, n_mix); double a4 = interpolate2 (n, A4, num_data, n_mix); double a5 = interpolate2 (n, A5, num_data, n_mix); double log_keq; double Z = 10000.0/T; switch (model) { case PARK85: log_keq = a1 + a2*Z + a3*Z*Z + a4*pow(Z, 3.0) + a5*pow(Z, 4.0); break; case PARK90: log_keq = a1/Z + a2 + a3*log(Z) + a4*Z + a5*Z*Z; break; case PARK94: log_keq = a1 + a2*log(Z) + a3*Z + a4*pow(Z, 2.0) + a5*pow(Z, 3.0); break; } if (log_keq != log_keq || fabs(log_keq) == numeric_limits<double>::infinity()) { Error_message_type error_message; error_message.module_name ="CHEMISTRY-REACTION"; error_message.location_primary_name = "N/A"; error_message.location_secondary_name = "N/A"; error_message.message = " Problem in the calculation of equilibrium constant!"; error_message.print_message(); } return (log_keq); }
double REACTION_KEQ::calculate_dKeq_dT_over_Keq(double T, double n_mix) { double a1 = interpolate2 (n, A1, num_data, n_mix); double a2 = interpolate2 (n, A2, num_data, n_mix); double a3 = interpolate2 (n, A3, num_data, n_mix); double a4 = interpolate2 (n, A4, num_data, n_mix); double a5 = interpolate2 (n, A5, num_data, n_mix); double dKeq_dT_over_Keq; double Z = 10000.0/T; switch (model) { case PARK85: dKeq_dT_over_Keq = -(a2*Z + 2.0*a3*Z*Z + 3.0*a4*pow(Z, 3.0) + 4.0*a5*pow(Z, 4.0)) / T; break; case PARK90: dKeq_dT_over_Keq = -(a1/Z + a3 + a4*Z + 2.0*a5*Z*Z) / T; break; case PARK94: dKeq_dT_over_Keq = -(a2 + a3*Z + 2.0*a4*Z*Z + 3.0*a5*pow(Z, 3.0)) / T; break; } if (dKeq_dT_over_Keq != dKeq_dT_over_Keq || fabs(dKeq_dT_over_Keq) == numeric_limits<double>::infinity()) { Error_message_type error_message; error_message.module_name ="CHEMISTRY-REACTION"; error_message.location_primary_name = "N/A"; error_message.location_secondary_name = "N/A"; error_message.message = " Problem in the calculation of dKeq_dT_over_Keq!"; error_message.print_message(); } return (dKeq_dT_over_Keq); }
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(); }