std::vector<Pose> cubicSpline_LineSegmentIntersection(const CubicSpline &s, const LineSegment &ls) { // unpack the x and y splines using namespace alglib; real_2d_array tbly, tblx; ae_int_t ny, nx; alglib::spline1dunpack(s.getSplineX(), nx, tblx); alglib::spline1dunpack(s.getSplineY(), ny, tbly); // both should have same number of pieces assert(nx == ny); int n = nx; vector<Pose> results; for (int i = 0; i < n-1; i++) { // confirm that u intervals are same for both x and y splines assert(tbly[i][0] == tblx[i][0] && tbly[i][1] == tblx[i][1]); double u_low = tbly[i][0], u_high = tbly[i][1]; double cX[4], cY[4]; for (int j = 0; j < 4; j++) { cX[j] = tblx[i][j+2]; cY[j] = tbly[i][j+2]; } vector<double> u = cubic_LineSegmentIntersection(cX, cY, u_low, u_high, ls); for (int i = 0; i < u.size(); i++) { double x = cX[0] + cX[1]*u[i] + cX[2]*u[i]*u[i] + cX[3]*u[i]*u[i]*u[i]; double y = cY[0] + cY[1]*u[i] + cY[2]*u[i]*u[i] + cY[3]*u[i]*u[i]*u[i]; results.push_back(Pose(x*fieldXConvert, y*fieldXConvert, 0)); } } return results; }
CubicSpline* EAM::getPhi(AtomType* atomType1, AtomType* atomType2) { EAMAdapter ea1 = EAMAdapter(atomType1); EAMAdapter ea2 = EAMAdapter(atomType2); CubicSpline* z1 = ea1.getZ(); CubicSpline* z2 = ea2.getZ(); // Thise prefactors convert the charge-charge interactions into // kcal / mol all were computed assuming distances are measured in // angstroms Charge-Charge, assuming charges are measured in // electrons. Matches value in Electrostatics.cpp pre11_ = 332.0637778; // make the r grid: // we need phi out to the largest value we'll encounter in the radial space; RealType rmax = 0.0; rmax = max(rmax, ea1.getRcut()); rmax = max(rmax, ea1.getNr() * ea1.getDr()); rmax = max(rmax, ea2.getRcut()); rmax = max(rmax, ea2.getNr() * ea2.getDr()); // use the smallest dr (finest grid) to build our grid: RealType dr = min(ea1.getDr(), ea2.getDr()); int nr = int(rmax/dr + 0.5); vector<RealType> rvals; for (int i = 0; i < nr; i++) rvals.push_back(RealType(i*dr)); // construct the pair potential: vector<RealType> phivals; RealType phi; RealType r; RealType zi, zj; phivals.push_back(0.0); for (unsigned int i = 1; i < rvals.size(); i++ ) { r = rvals[i]; // only use z(r) if we're inside this atom's cutoff radius, // otherwise, we'll use zero for the charge. This effectively // means that our phi grid goes out beyond the cutoff of the // pair potential zi = r <= ea1.getRcut() ? z1->getValueAt(r) : 0.0; zj = r <= ea2.getRcut() ? z2->getValueAt(r) : 0.0; phi = pre11_ * (zi * zj) / r; phivals.push_back(phi); } CubicSpline* cs = new CubicSpline(); cs->addPoints(rvals, phivals); return cs; }
void EAM::addExplicitInteraction(AtomType* atype1, AtomType* atype2, RealType dr, int nr, vector<RealType> phiVals) { // in case these weren't already in the map addType(atype1); addType(atype2); EAMInteractionData mixer; CubicSpline* cs = new CubicSpline(); vector<RealType> rVals; for (int i = 0; i < nr; i++) rVals.push_back(i * dr); cs->addPoints(rVals, phiVals); mixer.phi = cs; mixer.rcut = mixer.phi->getLimits().second; mixer.explicitlySet = true; int eamtid1 = EAMtids[ atype1->getIdent() ]; int eamtid2 = EAMtids[ atype2->getIdent() ]; MixingMap[eamtid1][eamtid2] = mixer; if (eamtid2 != eamtid1) { MixingMap[eamtid2][eamtid1] = mixer; } return; }
// Calculate Paramater B for LoadBasedScreen1 //##ModelId=40A1898A0191 double LoadBasedScreen1::CalculateB( double FractOS ) { double B = 0; const int nRowsB = 7; static double BArray [ nRowsB ] [ 2 ] = { // Fract B // Oversize Oversize // in Feed Factor { 0.00 , 1.60 }, { 0.50 , 1.00 }, { 0.80 , 0.64 }, { 0.85 , 0.56 }, { 0.90 , 0.44 }, { 0.95 , 0.24 }, { 1.00 , 0.00 }, }; double* p = (pBArray ? pBArray : *BArray); Matrix BMatrix( nRowsB, 2, p ); CubicSpline BSpline; BSpline.SetSpline ( BMatrix.column(0), BMatrix.column(1) ); B = BSpline.CalculateY ( FractOS ); // Vector TempSplineVec( nRows ); // SPN3( nRows, BMatrix.column(0), BMatrix.column(1), TempSplineVec ); // B = SPNV3( nRows, BMatrix.column(0), BMatrix.column(1), TempSplineVec, FractOS ); return B; }
void PiecewiseCubicSpline::calculateSplines() { mSplines.clear(); int numCtrlPoints = static_cast<int>(mCtrlPoints.size()); for (int i = 0; i < numCtrlPoints - 1; ++i) { CubicSpline spline; spline.SetControlPoints(mCtrlPoints[i].p, mCtrlPoints[i + 1].p, mCtrlPoints[i].v, mCtrlPoints[i + 1].v); mSplines.push_back(spline); } }
void SC::addExplicitInteraction(AtomType* atype1, AtomType* atype2, RealType epsilon, RealType m, RealType n, RealType alpha) { // in case these weren't already in the map addType(atype1); addType(atype2); SCInteractionData mixer; mixer.epsilon = epsilon; mixer.m = m; mixer.n = n; mixer.alpha = alpha; mixer.rCut = 2.0 * mixer.alpha; RealType dr = mixer.rCut / (np_ - 1); vector<RealType> rvals; vector<RealType> vvals; vector<RealType> phivals; rvals.push_back(0.0); vvals.push_back(0.0); phivals.push_back(0.0); for (int k = 1; k < np_; k++) { RealType r = dr * k; rvals.push_back(r); vvals.push_back( mixer.epsilon * pow(mixer.alpha/r, mixer.n) ); phivals.push_back( pow(mixer.alpha/r, mixer.m) ); } mixer.vCut = mixer.epsilon * pow(mixer.alpha/mixer.rCut, mixer.n); CubicSpline* V = new CubicSpline(); V->addPoints(rvals, vvals); CubicSpline* phi = new CubicSpline(); phi->addPoints(rvals, phivals); mixer.V = V; mixer.phi = phi; mixer.explicitlySet = true; int sctid1 = SCtids[ atype1->getIdent() ]; int sctid2 = SCtids[ atype2->getIdent() ]; MixingMap[sctid1][sctid2] = mixer; if (sctid2 != sctid1) { MixingMap[sctid2][sctid1] = mixer; } return; }
// Calculate Paramater C for LoadBasedScreen1 //##ModelId=40A1898A019B double LoadBasedScreen1::CalculateC( double FractHS ) { double C = 0; const int nRowsC = 18; static double CArray [ nRowsC ] [ 2 ] = { // Fract of C // Feed < S/2 // Factor { 0.00 , 0.70 }, { 0.25 , 1.00 }, { 0.30 , 1.06 }, { 0.35 , 1.13 }, { 0.40 , 1.21 }, { 0.45 , 1.30 }, { 0.50 , 1.40 }, { 0.55 , 1.52 }, { 0.60 , 1.67 }, { 0.65 , 1.85 }, { 0.70 , 2.05 }, { 0.75 , 2.26 }, { 0.80 , 2.50 }, { 0.85 , 2.75 }, { 0.90 , 3.20 }, { 0.95 , 4.00 }, { 0.98 , 6.00 }, { 1.00 , 10.00 }, }; double* p = (pCArray ? pCArray : *CArray); Matrix CMatrix( nRowsC, 2, p ); CubicSpline CSpline; CSpline.SetSpline ( CMatrix.column(0), CMatrix.column(1) ); C = CSpline.CalculateY ( FractHS ); // Vector TempSplineVec( nRows ); // SPN3( nRows, CMatrix.column(0), CMatrix.column(1), TempSplineVec ); // C = SPNV3( nRows, CMatrix.column(0), CMatrix.column(1), TempSplineVec, FractHS ); return C; }
// // Render a spline curve // void Spline(CubicSpline &curve, Color c, Bool normals, U32 normalMesh) { const U32 STEPS = 10; if (curve.length < 1e-4F) { return; } F32 step = curve.length / F32(STEPS); Vector v0 = curve.Step(0.0F); Vector v1, tangent; for (U32 i = 1; i <= STEPS; i++) { v1 = curve.Step(F32(i) * step, &tangent); // Draw the line FatLine(v0, v1, c, 0.15F); // Draw normals if (normals) { F32 veloc = tangent.Magnitude(); Matrix m = Matrix::I; m.posit = v1; // Normalize if (veloc > 1e-4) { tangent *= 1.0F / veloc; m.SetFromFront(tangent); } Common::Display::Mesh(normalMesh, m, c); // "TerrainMarker" } // Swap points v0 = v1; } }
//compute the camera path using the camera keyframes void computeCubicSplineCameraPath() { //Build the cubic splines CubicSpline splineEyePosition; CubicSpline splineLookAt; vector<int> keyIdFrame; //Add points CubicSpline for (unsigned int fc = 0; fc <= LarmorPhysx::ConfigManager::total_anim_steps; ++fc) { Camera cam = loadCamera(fc); if(cam.keyframe) { cout << "Add point to camera path: frame: " << fc << endl; splineEyePosition.addPoint(cam.eyePosition); splineLookAt.addPoint(cam.lookAt); keyIdFrame.push_back(fc); } } //compute paths splineEyePosition.compute(); splineLookAt.compute(); //draw camera path getting the points from the spline objects for(int kf = 0; kf < keyIdFrame.size()-1; kf++) { int fc0 = keyIdFrame.at(kf); int fc1 = keyIdFrame.at(kf+1); int framesInterval = fc1 - fc0; double frameStep = 1.0L / framesInterval; double cubicPos = 0.0; cout << "interpolation from keyframe: " << fc0 << endl; for(int pf = fc0+1; pf < fc1; pf++) { cout << "interpolation frame: " << pf << endl; cubicPos += frameStep; LVector3 eyePosition = splineEyePosition.getPoint(kf, cubicPos); LVector3 lookAt = splineLookAt.getPoint(kf, cubicPos); //Create the Camera object and save Camera camera; camera.idFrame = pf; camera.eyePosition = eyePosition; camera.lookAt = lookAt; camera.keyframe = false; //Save camera saveCamera(camera); } cout << "interpolation to keyframe: " << fc1 << endl; } }
// Calculate Paramater A for LoadBasedScreen1 //##ModelId=40A1898A017D double LoadBasedScreen1::CalculateA( double S ) { double A = 0; const int nRowsA = 19; static double AArray [ nRowsA ] [ 2 ] = { // S A // Screen Basic // Opening Capacity { 0 , 0.0 }, { 1 , 1.1 }, { 2 , 2.0 }, { 3 , 3.0 }, { 4 , 3.9 }, { 5 , 4.8 }, { 6.35 , 5.9 }, { 8 , 7.0 }, { 10 , 8.2 }, { 12 , 9.4 }, { 15 , 10.7 }, { 18 , 12.0 }, { 22 , 13.4 }, { 26 , 14.6 }, { 30 , 15.8 }, { 40 , 18.2 }, { 75 , 25.0 }, { 160 , 41.5 }, { 500 , 107.5 }, }; double* p = (pAArray ? pAArray : *AArray); Matrix AMatrix( nRowsA, 2, p ); CubicSpline ASpline; ASpline.SetSpline( AMatrix.column(0), AMatrix.column(1) ); A = ASpline.CalculateY ( S ); return A; }
double ParzDens_1::density ( double x ) { int i ; double sum, diff ; if (spline != NULL) return spline->evaluate ( x ) ; sum = 0.0 ; for (i=0 ; i<nd ; i++) { diff = x - d[i]; sum += exp ( -0.5 * diff * diff / var ) ; } return sum * factor ; }
int main(){ Mat img(1000, 800, CV_8UC3); img = Scalar::all(0); vector<Point> mousev,kalmanv; mousev.clear(); kalmanv.clear(); mousePos.clear(); float startThetaX = 0, endThetaX, startThetaY = 0, endThetaY; namedWindow("nimble", 1); setMouseCallback("nimble", CallBackFunc, NULL); int check = 0; int numPoints = 5; cout << img.cols << endl; while(1) { imshow("nimble", img); if(mousePos.size() > numPoints){ //cout << "hjere1:" << endl; Pose start(mousePos[0].x , mousePos[0].y , 0); Pose end(mousePos[numPoints].x, mousePos[numPoints].y, 0); vector<Pose> midpoints; for(int i = 1; i <numPoints; i++) midpoints.push_back(Pose(mousePos[i].x , mousePos[i].y , 0)); CubicSpline *p = new CubicSpline(start, end, midpoints); //cout << "hjere:" << endl; for(int i = 0; i < 1000 ;i++){ if((p->x(i/1000.) >= 0) && (p->x(i/1000.) < img.rows) && (p->y(i/1000.) >=0) && (p->y(i/1000.) < img.cols)) img.at<Vec3b>(Point(p->x(i/1000.), p->y(i/1000.))) = 255; } mousePos.erase(mousePos.begin(), mousePos.begin() + numPoints ); } waitKey(16); // break; } return 0; }
/** * Create a set of points on the heightfield for a 2D polyline by draping the point onto * the surface. * * \param line The 2D line to drape, in Earth coordinates. * \param fSpacing The approximate spacing of the surface tessellation, used to * decide how finely to tessellate the line. * \param fOffset An offset to elevate each point in the resulting geometry, * useful for keeping it visibly above the ground. * \param bInterp True to interpolate between the vertices of the input * line. This is generally desirable when the ground is much more finely * spaced than the input line. * \param bCurve True to interpret the vertices of the input line as * control points of a curve. The created geometry will consist of * a draped line which passes through the control points. * \param bTrue True to use the true elevation of the terrain, ignoring * whatever scale factor is being used to exaggerate elevation for * display. * \param output Received the points. * \return The approximate length of the resulting 3D polyline. */ float vtHeightField3d::LineOnSurface(const DLine2 &line, float fSpacing, float fOffset, bool bInterp, bool bCurve, bool bTrue, FLine3 &output) { uint i, j; FPoint3 v1, v2, v; float fTotalLength = 0.0f; int iVerts = 0; uint points = line.GetSize(); if (bCurve) { DPoint2 p2, last(1E9,1E9); DPoint3 p3; int spline_points = 0; CubicSpline spline; for (i = 0; i < points; i++) { p2 = line[i]; if (i > 1 && p2 == last) continue; p3.Set(p2.x, p2.y, 0); spline.AddPoint(p3); spline_points++; last = p2; } spline.Generate(); // Estimate how many steps to subdivide this line into const double dLinearLength = line.Length(); float fLinearLength, dummy; m_LocalCS.VectorEarthToLocal(DPoint2(dLinearLength, 0.0), fLinearLength, dummy); double full = (double) (spline_points-1); int iSteps = (uint) (fLinearLength / fSpacing); if (iSteps < 3) iSteps = 3; double dStep = full / iSteps; FPoint3 last_v; for (double f = 0; f <= full; f += dStep) { spline.Interpolate(f, &p3); m_LocalCS.EarthToLocal(p3.x, p3.y, v.x, v.z); FindAltitudeAtPoint(v, v.y, bTrue); v.y += fOffset; output.Append(v); iVerts++; // keep a running total of approximate ground length if (f > 0) fTotalLength += (v - last_v).Length(); last_v = v; } } else { // not curved: straight line in earth coordinates FPoint3 last_v; for (i = 0; i < points; i++) { if (bInterp) { v1 = v2; m_LocalCS.EarthToLocal(line[i].x, line[i].y, v2.x, v2.z); if (i == 0) continue; // estimate how many steps to subdivide this segment into FPoint3 diff = v2 - v1; float fLen = diff.Length(); uint iSteps = (uint) (fLen / fSpacing); if (iSteps < 1) iSteps = 1; for (j = (i == 1 ? 0:1); j <= iSteps; j++) { // simple linear interpolation of the ground coordinate v.Set(v1.x + diff.x / iSteps * j, 0.0f, v1.z + diff.z / iSteps * j); FindAltitudeAtPoint(v, v.y, bTrue); v.y += fOffset; output.Append(v); iVerts++; // keep a running total of approximate ground length if (j > 0) fTotalLength += (v - last_v).Length(); last_v = v; } } else { m_LocalCS.EarthToLocal(line[i], v.x, v.z); FindAltitudeAtPoint(v, v.y, bTrue); v.y += fOffset; output.Append(v); } } } return fTotalLength; }
void EAM::calcForce(InteractionData &idat) { if (!initialized_) initialize(); if (haveCutoffRadius_) if ( *(idat.rij) > eamRcut_) return; int eamtid1 = EAMtids[idat.atid1]; int eamtid2 = EAMtids[idat.atid2]; EAMAtomData &data1 = EAMdata[eamtid1]; EAMAtomData &data2 = EAMdata[eamtid2]; // get type-specific cutoff radii RealType rci = data1.rcut; RealType rcj = data2.rcut; RealType rha(0.0), drha(0.0), rhb(0.0), drhb(0.0); RealType pha(0.0), dpha(0.0), phb(0.0), dphb(0.0); RealType phab(0.0), dvpdr(0.0); RealType drhoidr, drhojdr, dudr; if ( *(idat.rij) < rci) { data1.rho->getValueAndDerivativeAt( *(idat.rij), rha, drha); CubicSpline* phi = MixingMap[eamtid1][eamtid1].phi; phi->getValueAndDerivativeAt( *(idat.rij), pha, dpha); } if ( *(idat.rij) < rcj) { data2.rho->getValueAndDerivativeAt( *(idat.rij), rhb, drhb ); CubicSpline* phi = MixingMap[eamtid2][eamtid2].phi; phi->getValueAndDerivativeAt( *(idat.rij), phb, dphb); } switch(mixMeth_) { case eamJohnson: if ( *(idat.rij) < rci) { phab = phab + 0.5 * (rhb / rha) * pha; dvpdr = dvpdr + 0.5*((rhb/rha)*dpha + pha*((drhb/rha) - (rhb*drha/rha/rha))); } if ( *(idat.rij) < rcj) { phab = phab + 0.5 * (rha / rhb) * phb; dvpdr = dvpdr + 0.5 * ((rha/rhb)*dphb + phb*((drha/rhb) - (rha*drhb/rhb/rhb))); } break; case eamDaw: if ( *(idat.rij) < MixingMap[eamtid1][eamtid2].rcut) { MixingMap[eamtid1][eamtid2].phi->getValueAndDerivativeAt( *(idat.rij), phab, dvpdr); } break; case eamUnknown: default: sprintf(painCave.errMsg, "EAM::calcForce hit a mixing method it doesn't know about!\n" ); painCave.severity = OPENMD_ERROR; painCave.isFatal = 1; simError(); } drhoidr = drha; drhojdr = drhb; dudr = drhojdr* *(idat.dfrho1) + drhoidr* *(idat.dfrho2) + dvpdr; *(idat.f1) += *(idat.d) * dudr / *(idat.rij); if (idat.doParticlePot) { // particlePot is the difference between the full potential and // the full potential without the presence of a particular // particle (atom1). // // This reduces the density at other particle locations, so we // need to recompute the density at atom2 assuming atom1 didn't // contribute. This then requires recomputing the density // functional for atom2 as well. *(idat.particlePot1) += data2.F->getValueAt( *(idat.rho2) - rha ) - *(idat.frho2); *(idat.particlePot2) += data1.F->getValueAt( *(idat.rho1) - rhb) - *(idat.frho1); } (*(idat.pot))[METALLIC_FAMILY] += phab; *(idat.vpair) += phab; return; }
bool CubicSpline::intersects(const CubicSpline &rt, VectorF ignoreAxis) const { #if 1 vector<VectorF> path1 = getSplinePoints(*this); vector<VectorF> path2 = getSplinePoints(rt); for(size_t i = 1; i < path1.size(); i++) { for(size_t j = 1; j < path2.size(); j++) { if(linesIntersect(path1[i - 1], path1[i], path2[j - 1], path2[j], 0)) return true; } } return false; #else const int splitCount = 50; // number of line segments to split spline into ignoreAxis = normalize(ignoreAxis); for(int segmentNumber = 0; segmentNumber < splitCount; segmentNumber++) { float startT = (float)(segmentNumber) / splitCount; float endT = (float)(segmentNumber + 1) / splitCount; VectorF startP = rt.evaluate(startT); startP -= ignoreAxis * dot(ignoreAxis, startP); // move to plane normal to ignoreAxis VectorF endP = rt.evaluate(endT); endP -= ignoreAxis * dot(ignoreAxis, endP); // move to plane normal to ignoreAxis VectorF delta = endP - startP; if(absSquared(delta) < eps * eps) // if delta is too small { continue; } // solve dot(evaluate(t), cross(ignoreAxis, delta)) == 0 and it intersects if dot(evaluate(t) - startP, delta) / dot(delta, delta) is in [0, 1] and t is in [0, 1] VectorF normal = cross(ignoreAxis, delta); float cubic = dot(getCubic(), normal); float quadratic = dot(getQuadratic(), normal); float linear = dot(getLinear(), normal); float constant = dot(getConstant(), normal); float intersections[3]; int intersectionCount = solveCubic(constant, linear, quadratic, cubic, intersections); for(int i = 0; i < intersectionCount; i++) { float t = intersections[i]; if(t < 0 || t > 1) { continue; } float v = dot(evaluate(t) - startP, delta) / dot(delta, delta); if(v < 0 || v > 1) { continue; } return true; } } return false; #endif }
void SC::addType(AtomType* atomType){ SuttonChenAdapter sca = SuttonChenAdapter(atomType); SCAtomData scAtomData; scAtomData.c = sca.getC(); scAtomData.m = sca.getM(); scAtomData.n = sca.getN(); scAtomData.alpha = sca.getAlpha(); scAtomData.epsilon = sca.getEpsilon(); scAtomData.rCut = 2.0 * scAtomData.alpha; // add it to the map: int atid = atomType->getIdent(); int sctid = SCtypes.size(); pair<set<int>::iterator,bool> ret; ret = SCtypes.insert( atid ); if (ret.second == false) { sprintf( painCave.errMsg, "SC already had a previous entry with ident %d\n", atid ); painCave.severity = OPENMD_INFO; painCave.isFatal = 0; simError(); } SCtids[atid] = sctid; SCdata[sctid] = scAtomData; MixingMap[sctid].resize(nSC_); // Now, iterate over all known types and add to the mixing map: std::set<int>::iterator it; for( it = SCtypes.begin(); it != SCtypes.end(); ++it) { int sctid2 = SCtids[ (*it) ]; AtomType* atype2 = forceField_->getAtomType( (*it) ); SCInteractionData mixer; mixer.alpha = getAlpha(atomType, atype2); mixer.rCut = 2.0 * mixer.alpha; mixer.epsilon = getEpsilon(atomType, atype2); mixer.m = getM(atomType, atype2); mixer.n = getN(atomType, atype2); RealType dr = mixer.rCut / (np_ - 1); vector<RealType> rvals; vector<RealType> vvals; vector<RealType> phivals; rvals.push_back(0.0); vvals.push_back(0.0); phivals.push_back(0.0); for (int k = 1; k < np_; k++) { RealType r = dr * k; rvals.push_back(r); vvals.push_back( mixer.epsilon * pow(mixer.alpha/r, mixer.n) ); phivals.push_back( pow(mixer.alpha/r, mixer.m) ); } mixer.vCut = mixer.epsilon * pow(mixer.alpha/mixer.rCut, mixer.n); CubicSpline* V = new CubicSpline(); V->addPoints(rvals, vvals); CubicSpline* phi = new CubicSpline(); phi->addPoints(rvals, phivals); mixer.V = V; mixer.phi = phi; mixer.explicitlySet = false; MixingMap[sctid2].resize( nSC_ ); MixingMap[sctid][sctid2] = mixer; if (sctid2 != sctid) { MixingMap[sctid2][sctid] = mixer; } } return; }
//##ModelId=40A1898902EF bool LoadBasedScreen1::CalculateModel( PFlowStream1 FeedStream ) { // Local Variables int i = 0; int j = 0; double ScaleFactor = 0.00; double Denom = 0.00; Vector CombCPPSizing ( nSize ); CubicSpline FeedSpline; MatrixView FeedSolids = FeedStream->AccessSolidsMatrix( ); MatrixView OversizeSolids = Oversize->AccessSolidsMatrix( ); MatrixView UndersizeSolids = Undersize->AccessSolidsMatrix( ); // Ensure correct shape feed matrix if( FeedSolids.rowCount() != nSize ) goto calcFailed; if( FeedSolids.columnCount() != nType ) goto calcFailed; // Calculate total feed flow rate (solids) QF = FeedSolids.sum( ); // Convert feed matrix into single component size distribution for( i = 0; i < nSize; i++ ) CombRetSizing[ i ] = (FeedSolids.row(i)).sum(); if (fabs(QF)<1e-8) ScaleFactor = 0.00; else ScaleFactor = 1/QF; // Scale single component distribution to cumulative sizing // scaled to fraction basis: ie. 1 passes top-size CombCPPSizing[ nSize - 1 ] = 0; for( i = nSize - 2; i >=0; i-- ) CombCPPSizing[ i ] = CombCPPSizing[i + 1] + ( CombRetSizing[i + 1] * ScaleFactor ); // Construct cubic spline passing through cumulative curve FeedSpline.SetSpline( Sizes, CombCPPSizing ); // Use cubic spline to get fraction passing half apperture size Feed_HS = FeedSpline.CalculateY( S/2 ); // Use spline to get fraction passing apperture size U = Feed_US = FeedSpline.CalculateY( S ); Feed_OS = 1 - Feed_US; // Calculate area factors for this screen A = CalculateA( S ); B = CalculateB( Feed_OS ); C = CalculateC( Feed_HS ); D = CalculateD( DL ); E = CalculateE( WS, S ); H = CalculateH( OT ); J = CalculateJ( ST, S, OA ); K = CalculateK( FT ); L = CalculateL(); X = CalculateX( CF ); // Calculate denominator of load equation - ensure not zero Denom = A * B * C * D * E * F * H * J * K * L * AF * X; if (fabs(Denom)<1e-8) Denom = 1e-8; // Calculate load V = ( 90 * QF * U ) / ( Denom ); // Calculate efficiency that matches this load T = CalculateT( V ); // Calculate factor G G = ( V * T ) / 90; // calculate flow to undersize at this efficiency QU = QF * U * T; // Solve for D50 that matches the undersize flow D50 = zbrent( S * 0.1, S * 0.99, TOLERANCE ); // Calculate splitting of feed water to products Undersize->SetLiquidMass( FeedStream->GetLiquidMass() * WR ); Oversize->SetLiquidMass( FeedStream->GetLiquidMass() * (1-WR) ); // Calculate splitting of solids components to products for( i=0; i<nType; i++ ) { for( j=0; j<nSize; j++ ) { double feed = FeedSolids[j][i]; OversizeSolids[j][i] = feed * PartitionCurve[j]; UndersizeSolids[j][i] = feed * ( 1 - PartitionCurve[j] ); } } // Setup model output vector ModelOutput[0] = QF; ModelOutput[1] = Feed_OS; ModelOutput[2] = Feed_US; ModelOutput[3] = Feed_HS; ModelOutput[4] = QU; ModelOutput[5] = QF - QU; ModelOutput[6] = S; ModelOutput[7] = T; ModelOutput[8] = AF; ModelOutput[9] = D50; ModelOutput[10] = A; ModelOutput[11] = B; ModelOutput[12] = C; ModelOutput[13] = D; ModelOutput[14] = E; ModelOutput[15] = F; ModelOutput[16] = G; ModelOutput[17] = H; ModelOutput[18] = J; ModelOutput[19] = K; ModelOutput[20] = L; ModelOutput[21] = X; ModelOutput[22] = V; // Indicate success return true; calcFailed: // Indicate failure return false; }