📄 meshset.c
字号:
} } else { d = 1.0 - 4*a*c/(b*b); if (d >= 0.0) { f = (1.0 + sqrt(d))/2.0; *rp = - (b*f)/a; *rn = - c/(b*f); } else { return(FALSE); } } return(TRUE);}/* * Name: twoSideSpacing * Purpose: Find a compatible set of ratios and node numbers when the * spacing is constrained at both ends of a span. * Formals: < I > width: size the span * < I > hStart: spacing at start of span * < I > hEnd: spacing at end of span * < I > rWanted: desired ratio of spacings * < O > rSfound: ratio found for start of span * < O > rEfound: ratio found for end of span * < O > nSfound: number of start spaces * < O > nEfound: number of end spaces * Returns: OK / E_PRIVATE * Users: MESHspacing * Calls: twoSideRatio, error-message handler */static inttwoSideSpacing( width, hStart, hEnd, rWanted, rSfound, rEfound, nSfound, nEfound )double width;double hStart, hEnd;double rWanted, *rSfound, *rEfound;int *nSfound, *nEfound;{ int nSpaceS; /* Number of spaces at the start */ int nSpaceE; /* Number of spaces at the end */ int nSpaceT; /* Number of spaces total */ double dSpaceS; /* Exact value of nSpaceS */ double dSpaceE; /* Exact value of nSpaceE */ double dSpaceT; /* Exact value of nSpaceT */ double dDiff; /* Difference between dSpaceS & dSpaceE */ double remaining; /* Length of span between hs and he */ double rTempS, rTempE; /* For temporarily calc'ed ratios */ double hsLast, heLast; /* Used to ensure ratio is valid */ double rConnect, rMin, rMax; /* " */ double hMax, hMin; /* Max and min between hStart and hEnd */ double tmp; int i,j; /* Indices for searching for best ratio */ int solnFound; /* For partial search termination */ int solnError; /* For partial search termination */ int nSaveS = 0; /* Saves best solution so far */ int nSaveE = 0; /* " */ double rSaveS = 0.0; /* " */ double rSaveE = 0.0; /* " */ char errBuf[80];/* * It's an error if there isn't enough width to fit in both spaces. */ remaining = width - (hStart + hEnd); if (remaining < 0.0) { sprintf( errBuf, "two-sided spacing can't find an acceptable solution\n"); SPfrontEnd->IFerror( ERR_WARNING, errBuf, NIL(IFuid) ); *rSfound = *rEfound = 0.0; *nSfound = *nEfound = 0; return(E_PRIVATE); }/* Adjust ratio wanted to acceptable limits, and find number of extra spaces * needed to bring the smaller ratio up to the size of the bigger one. */ hMax = MAX( hStart, hEnd ); hMin = MIN( hStart, hEnd ); if ( hMax == hMin ) { dDiff = 0.0; } else {/* Does a solution exist if we allow the number of spaces to take on * a non-integral value? * If not, then adjust the ratio to lie within acceptable bounds. * Since the choice of whether or not to require a peak in the plot * of "spacing vs number" is arbitrary, both cases are checked, and * the one that gives the closest answer to the original ratio * is chosen. The function quadRoots is used to find limits for the * ratio in the peaked case. The unpeaked case can find a lower * bound more easily. */ if (quadRoots( hMax, hMax - width, remaining, &rTempS, &rTempE )) { rWanted = MIN(rWanted, rTempS); rTempS = 1.0 + (hMax - hMin)/(width - hMax); rWanted = MAX(rWanted, rTempS); if ((rWanted != rTempS) && (rTempE > rWanted)) { if (ABS(rWanted - rTempE) < 4.0*ABS(rWanted - rTempS)) { rWanted = rTempE; } else { rWanted = rTempS; } } } else { /* Complex roots */ rTempS = 1.0 + (hMax - hMin)/(width - hMax); rWanted = MAX(rWanted, rTempS); } dDiff = log(hMax/hMin)/log(rWanted); dDiff *= ( hStart < hEnd ) ? -1.0 : 1.0; }/* Find the number of spaces at the start and at the end. *//* Handle ratio near 1.0 carefully. */ if ( ABS(rWanted - 1.0) < 1.0e-4 ) { dSpaceS = (width - dDiff*hEnd)/(hStart+hEnd); } else { tmp = (hStart+hEnd-width+width*rWanted)/ (hStart+hEnd*pow(rWanted,dDiff)); dSpaceS = log(tmp)/log(rWanted); } dSpaceE = dSpaceS + dDiff; dSpaceT = dSpaceS + dSpaceE;/* Search until an acceptable solution is found. Some * cases may be repeated, but no harm is done. */ for (i = 0; i <= 1; i++) { nSpaceT = (int)dSpaceT + i;/* Guess a starting point which is guaranteed to have a solution. */ nSpaceS = MIN( nSpaceT - 1, MAX( 4, (int) dSpaceS) ); nSpaceE = nSpaceT - nSpaceS; solnFound = solnError = FALSE; while ( !solnFound ) { /* Take care of special cases first. */ if ((nSpaceE <= 0) || (nSpaceS <= 0)) { solnError = TRUE; } else if (nSpaceT == 2) { /* Check for exact fit */ if (ABS(remaining) < 1.0e-3*hMax ) { rTempS = hEnd / hStart; rTempE = 1.0 / rTempS; nSpaceS = nSpaceE = 1; } else { solnError = TRUE; } } else if (nSpaceT == 3) { /* Trivial to solve */ if (remaining > 0.0) { rTempS = remaining / hStart; rTempE = remaining / hEnd; nSpaceS = 2; /* Always put middle space at start */ nSpaceE = 1; } else { solnError = TRUE; } } else { /* Finally, the general case */ if (remaining > 0.0) { rTempS = rWanted; twoSideRatio( width, hStart, hEnd, &rTempS, nSpaceS, nSpaceE ); rTempE = rTempS; } else { solnError = TRUE; } } if ( solnError ) break; /* while loop *//* Check whether the ratio discovered is good or not. */ hsLast = hStart*pow(rTempS, (double)nSpaceS-1.0); heLast = hEnd*pow(rTempE, (double)nSpaceE-1.0); rConnect = heLast/hsLast; if ( rConnect < 1.0/rTempE - RAT_TOL ) { nSpaceS--; nSpaceE++; } else if ( rConnect > rTempS + RAT_TOL ) { nSpaceS++; nSpaceE--; } else { solnFound = TRUE;/* Save if this solution is better than the previous one. */ if (ABS(rWanted - rTempS) <= ABS(rWanted - rSaveS)) { rSaveS = rTempS; rSaveE = rTempE; nSaveS = nSpaceS; nSaveE = nSpaceE; } } } }/* Prepare return values. */ if (rSaveS == 0.0) { sprintf( errBuf, "two-sided spacing can't find an acceptable solution\n"); SPfrontEnd->IFerror( ERR_WARNING, errBuf, NIL(IFuid) ); *rSfound = *rEfound = 0.0; *nSfound = *nEfound = 0; return(E_PRIVATE); } else { *rSfound = rSaveS; *rEfound = rSaveE; *nSfound = nSaveS; *nEfound = nSaveE; return(OK); }}/* * Name: twoSideRatio * Purpose: Finds the unique ratio 'r' which satisfies the * constraint: * w = hs*(1-r^ns)/(1-r) + he*(1-r^ne)/(1-r) * Formals: < I > w: size of a span * < I > hs: spacing at start of span * < I > he: spacing at end of span * <I/O> argRatio: returns r, contains initial guess for r * < I > ns: number of steps to take at start * < I > ne: number of steps to take at end * Returns: OK / E_PRIVATE * Users: twoSideSpacing * Calls: error-message handler */static inttwoSideRatio( w, hs, he, argRatio, ns, ne )double w;double hs, he;double *argRatio;int ns, ne;{ double funcLow, funcUpp, func; double ratLow, ratUpp, ratio = *argRatio; double dns = (double)ns; double dne = (double)ne; int i;/* Get lower bound on solution. */ ratLow = 0.0; funcLow = hs + he - w; if ((funcLow > 0.0) || ((funcLow < 0.0) && (MAX(ns,ne) <= 1))) { *argRatio = 0.0; return(E_PRIVATE); }/* Find upper bound on solution. */ ratUpp = ratio; do { ratUpp += 0.2; funcUpp = hs*geomSum(ratUpp, dns) + he*geomSum(ratUpp, dne) - w; } while (funcUpp < 0.0);/* Do bisections to find new ratio. */ for ( i=0; i < RAT_LIM; i++ ) { ratio = ratLow + 0.5 * (ratUpp - ratLow); func = hs*geomSum(ratio, dns) + he*geomSum(ratio, dne) - w; if ((func == 0.0) || (ratUpp - ratLow < RAT_TOL)) break; funcLow = hs*geomSum(ratLow, dns) + he*geomSum(ratLow, dne) - w; if (funcLow*func > 0.0) { ratLow = ratio; } else { ratUpp = ratio; } } if (i == RAT_LIM) { /* No solution found */ *argRatio = 0.0; return(E_PRIVATE); } else { *argRatio = ratio; return(OK); }}/* * Name: maxLimSpacing * Purpose: Find compatible number of spaces and ratio when the spacing * is constrained at start of a span, and has to be smaller * than a user-specified maximum at the end. * Formals: < I > width: width of the span * < I > hStart: spacing constraint at one end * < I > hMax: maximum spacing allowable * < I > rWanted: ideal ratio of one spacing to the next * < O > rFound: actual ratio discovered * < O > nSfound: number of start spaces * < O > nMfound: number of maximum spaces * Returns: OK / E_PRIVATE * Users: MESHspacing * Calls: oneSideRatio, stepsInSpan */static intmaxLimSpacing( width, hStart, hMax, rWanted, rFound, nSfound, nMfound )double width;double hStart, hMax;double rWanted, *rFound;int *nSfound, *nMfound;{ int nSpaceS; /* Number of spaces at the start */ int nSpaceM; /* Number of spaces with maximum size */ int nSpaceT; /* Total number of spaces */ double dSpaceS; /* Exact number of start spaces needed */ double dSpaceM; /* Exact number of max spaces needed */ double dSpaceT; /* Exact total number of spaces */ double rTempS; /* For temporarily calc'ed ratio */ double remaining; /* Width taken up by start spaces */ double rConnect, hBiggest; /* Used to ensure ratio is valid */ double rSaveS = 0.0; /* Saves best solution so far */ int nSaveS = 0; /* " */ int nSaveM = 0; /* " */ int i, j; /* Searching indices */ int solnFound; /* For partial search termination */ int solnError; /* For partial search termination */ char errBuf[80];/* Compute the ratio needed to exactly go from hStart to hMax * in the given width. If hMax is really big, then we know * the spaces can't exceed it. */ if ( width > hMax ) { rTempS = 1.0 + (hMax - hStart)/(width - hMax); } else { rTempS = 1.0e6; /* an impossibly large value */ } if (rWanted <= rTempS) { /* Spacings stay below maximum allowed */ dSpaceS = stepsInSpan( width, hStart, rWanted ); dSpaceM = 0.0; } else {/* Find number of spaces needed to increase hStart to hMax. */ dSpaceS = log(hMax/hStart)/log(rWanted); remaining = hStart*geomSum(rWanted, dSpaceS); dSpaceM = (width - remaining)/hMax; } dSpaceT = dSpaceS + dSpaceM;/* Search until an acceptable solution is found. Some * cases may be repeated, but no harm is done. */ for (i = 0; i <= 1; i++) { nSpaceT = (int)dSpaceT + i;/* Guess a starting point which is guaranteed to have a solution. */ nSpaceS = MIN( nSpaceT, MAX( 3, (int) dSpaceS) ); nSpaceM = nSpaceT - nSpaceS; solnFound = solnError = FALSE; while ( !solnFound ) { remaining = width - hMax*nSpaceM;/* Test for the various special cases first. */ if ( nSpaceM < 0 || nSpaceS <= 0 ) { solnError = TRUE; } else if (nSpaceS == 1) { /* check for exact fit */ if ( ABS(remaining - hStart) < 1.0e-3*hStart ) { hBiggest = hStart; if (nSpaceM == 0) { rTempS = 1.0; } else { rTempS = hMax / hStart; } } else { solnError = TRUE; } } else if (nSpaceS == 2) { /* Easy to solve */ if (remaining > hStart) { hBiggest = remaining - hStart; rTempS = hBiggest / hStart; } else { solnError = TRUE; } } else { if (remaining > hStart) { rTempS = rWanted; oneSideRatio( remaining, hStart, &rTempS, nSpaceS ); hBiggest = hStart*pow(rTempS, (double)nSpaceS - 1.0); } else { solnError = TRUE; } } if ( solnError ) break; /* while loop */ rConnect = hMax / hBiggest; if ( rConnect < 1.0 - RAT_TOL ) { nSpaceS--; nSpaceM++; } else if ( (rConnect > rTempS + RAT_TOL) && nSpaceM != 0 ) { nSpaceS++; nSpaceM--; } else { solnFound = TRUE;/* Save solution if it's better. */ if ( (rTempS >= 1.0 - RAT_TOL) && ABS(rWanted - rTempS) <= ABS(rWanted - rSaveS)) { rSaveS = rTempS; nSaveS = nSpaceS; nSaveM = nSpaceM; } } } }/* Prepare return values. */ if (rSaveS == 0.0) { sprintf( errBuf, "max-limited spacing can't find an acceptable solution\n"); SPfrontEnd->IFerror( ERR_WARNING, errBuf, NIL(IFuid) ); *rFound = 0.0; *nSfound = *nMfound = 0; return(E_PRIVATE); } else { *rFound = rSaveS; *nSfound = nSaveS; *nMfound = nSaveM; return(OK); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -