📄 meshset.c
字号:
double hStart, hEnd, hMax, hBig; double ratStart, ratEnd; int error = OK; char errBuf[512];/* Initialize list of coordinates. */ *coordList = endCoord = NIL(MESHcoord); *numCoords = totCoords = 0;/* Check the card list. */ if (error = MESHcheck( dim, cardList )) return( error );/* Print info header. */ #ifdef NOTDEF fprintf( stdout, " %c.Mesh Card Information\n", toupper(dim) ); fprintf( stdout, "-------------------------\n" ); fprintf( stdout, " %3s %3s %3s %9s %9s %9s %9s %9s %9s\n", "n.s", "n.m", "n.e", "l.e", "h.s", "h.e", "h.m", "r.s", "r.e" );#endif for ( card = cardList; card != NIL(MESHcard); card = card->MESHnextCard ) { cardNum++; locStart = card->MESHlocStart; locEnd = card->MESHlocEnd; if (locEnd == locStart) { /* This card has no width. *//* First update the node number. */ if (card->MESHnumberGiven) { if (card->MESHlocationGiven) { /* Absolute node number given */ numEnd = card->MESHnumber; if (cardNum == 1) numStart = numEnd; } else { /* Number of spaces instead */ numEnd = numStart + card->MESHnumber; } }/* Are node numbers in the wrong order? */ if ( numEnd < numStart ) { sprintf( errBuf, "%c.mesh card %d has out-of-order node numbers ( %d > %d )", dim, cardNum, numStart, numEnd ); SPfrontEnd->IFerror( ERR_FATAL, errBuf, NIL(IFuid) ); error = E_PRIVATE; } } else { /* This card has some width. *//* First update the node number. */ if (card->MESHnumberGiven) { /* Uniform mesh */ if (card->MESHlocationGiven) { /* Absolute node number given */ numEnd = card->MESHnumber; if (cardNum == 1) numStart = numEnd; nspStart = numEnd - numStart; } else { /* Number of spaces instead */ nspStart = card->MESHnumber; numEnd = numStart + nspStart; } ratStart = 1.0; ratEnd = 0.0; nspEnd = 0; nspMax = 0; if ( nspStart > 0 ) { card->MESHhStart = (locEnd - locStart) / (double)nspStart; card->MESHhEnd = 0.0; } } else { /* Nonuniform mesh */ error = MESHspacing( card, &ratStart, &ratEnd, &nspStart, &nspMax, &nspEnd ); if (error) { sprintf( errBuf, "%c.mesh card %d can't be spaced automatically", dim, cardNum ); SPfrontEnd->IFerror( ERR_FATAL, errBuf, NIL(IFuid) ); return( error ); } else { numEnd = numStart + nspStart + nspMax + nspEnd; } }/* Are the node numbers properly ordered? */ if ( numEnd <= numStart ) { sprintf( errBuf, "%c.mesh card %d results in out-of-order node numbers ( %d > %d )", dim, cardNum, numStart, numEnd ); SPfrontEnd->IFerror( ERR_FATAL, errBuf, NIL(IFuid) ); error = E_PRIVATE; } else {/* Create the new MESHcoord's. */ hStart = card->MESHhStart; hEnd = card->MESHhEnd; hMax = card->MESHhMax; hBig = 0.0;/* Generate the first coord in this section */ location = locStart; error = addCoord( coordList, &endCoord, ++totCoords, location ); if (error) return(error);/* Generate new coords for the starting section. */ nspLeft = nspStart + nspMax + nspEnd; if ( nspStart != 0 ) { hBig = MAX( hBig, hStart*pow( ratStart, (double) (nspStart - 1) ) ); space = hStart; for ( i = 0; (i < nspStart)&&(nspLeft > 1); i++, nspLeft-- ) { location += space; space *= ratStart; error = addCoord( coordList, &endCoord, ++totCoords, location ); if (error) return(error); } }/* Generate new coords for the maximum section. */ if ( nspMax != 0 ) { hBig = MAX( hBig, hMax ); space = hMax; for ( i = 0; (i < nspMax)&&(nspLeft > 1); i++, nspLeft-- ) { location += space; error = addCoord( coordList, &endCoord, ++totCoords, location ); if (error) return(error); } }/* Generate new coords for the ending section. */ if ( nspEnd != 0 ) { hBig = MAX( hBig, hEnd*pow( ratEnd, (double) (nspEnd - 1) ) ); space = hEnd * pow( ratEnd, (double) (nspEnd - 1) ); for ( i = 0; (i < nspEnd)&&(nspLeft > 1); i++, nspLeft-- ) { location += space; space /= ratEnd; error = addCoord( coordList, &endCoord, ++totCoords, location ); if (error) return(error); } }#ifdef NOTDEF fprintf( stdout, " %9.5f\n", locStart ); fprintf( stdout, " %3d %3d %3d %9.5f %9.5f %9.5f %9.5f %9.5f\n", nspStart, nspMax, nspEnd, hStart, hEnd, hBig, ratStart, ratEnd );#endif } }/* Return now if anything has failed. */ if (error) return(error);/* Advance the node number. */ numStart = numEnd; }/* * If the mesh is not empty, then the loop above has exited before * adding the final coord to the list. So we need to do that now. */ if (*coordList != NIL(MESHcoord)) { error = addCoord( coordList, &endCoord, ++totCoords, locEnd ); if (error) return(error);#ifdef NOTDEF fprintf( stdout, " %9.5f\n", locEnd );#endif }#ifdef NOTDEF fprintf( stdout, "\n" );#endif *numCoords = totCoords; return(OK);}/* * Name: MESHspacing * Purpose: Find ratios, spacings, and node numbers for a mesh span. * Formals: < I > card: the input card for this span * < O > rS: ratio found for spacings at start of span * < O > rE: ratio found for spacings at end of span * < O > nS: number of start spaces * < O > nM: number of max spaces * < O > nE: number of end spaces * Returns: OK / E_PRIVATE * Users: MESHsetup * Calls: oneSideSpacing, twoSideSpacing, maxLimSpacing */static intMESHspacing( card, rS, rE, nS, nM, nE )MESHcard *card;double *rS, *rE;int *nS, *nM, *nE;{ int error = OK; int hStartGiven = card->MESHhStartGiven; int hEndGiven = card->MESHhEndGiven; int hMaxGiven = card->MESHhMaxGiven; double hS = card->MESHhStart; double hE = card->MESHhEnd; double hM = card->MESHhMax; double rW = card->MESHratio; /* The ratio wanted */ double width; width = card->MESHlocEnd - card->MESHlocStart;/* Call subsidiary routine depending on how flags are set. */ if (!hStartGiven && hEndGiven && !hMaxGiven ) {/* End section only */ error = oneSideSpacing( width, hE, rW, rE, nE ); *nM = *nS = 0; *rS = 0.0; } else if ( hStartGiven && !hEndGiven && !hMaxGiven ) {/* Start section only */ error = oneSideSpacing( width, hS, rW, rS, nS ); *nM = *nE = 0; *rE = 0.0; } else if ( hStartGiven && hEndGiven && !hMaxGiven ) {/* Both a start and an end section */ error = twoSideSpacing( width, hS, hE, rW, rS, rE, nS, nE ); *nM = 0; } else if ( hStartGiven && !hEndGiven && hMaxGiven ) {/* Limited size in end section */ error = maxLimSpacing( width, hS, hM, rW, rS, nS, nM ); *nE = 0; *rE = 1.0; } else if (!hStartGiven && hEndGiven && hMaxGiven ) {/* Limited size in start section */ error = maxLimSpacing( width, hE, hM, rW, rE, nE, nM ); *nS = 0; *rS = 1.0; } else if ( hStartGiven && hEndGiven && hMaxGiven ) {/* Limited size somewhere in the middle */ /* NOT IMPLEMENTED */ /* error = midLimSpacing( width, hS, hE, hM, rW, rS, rE, nS, nE, nM ); */ error = E_PRIVATE; } else {/* Illegal situations */ error = E_PRIVATE; } return( error );}/* * Name: stepsInSpan * Purpose: Finds the number of steps needed to go a given distance * while increasing each step by a given ratio. * Formals: < I > width: size of total distance * < I > spacing: size of initial step * < O > ratio: increase with each step * Returns: number of steps * Users: spacing routines * Calls: log */static doublestepsInSpan( width, spacing, ratio )double width, spacing, ratio;{ double nSpaces;/* Handle ratios near 1.0 specially. */ if ( ABS(ratio - 1.0) < 1.0e-4 ) { nSpaces = (width/spacing); } else { nSpaces = (log(1.0-width*(1.0-ratio)/spacing)/log(ratio)); } return(nSpaces);}/* * Name: oneSideSpacing * Purpose: Find compatible number of spaces and ratio when the spacing * is constrained at one end of a span. * Formals: < I > width: width of the span * < I > spacing: spacing constraint * < I > rWanted: ideal ratio of one spacing to the next * < O > rFound: actual ratio discovered * < O > nFound: number of spaces found * Returns: OK / E_PRIVATE * Users: MESHspacing * Calls: oneSideRatio, stepsInSpan */static intoneSideSpacing( width, spacing, rWanted, rFound, nFound )double width;double spacing;double rWanted, *rFound;int *nFound;{ int nSpaces; /* Number of spaces */ double rTemp1, rTemp2; /* For temporarily calc'ed ratios */ char errBuf[80];/* Make sure we can take at least one step. */ if ( width < spacing ) { sprintf( errBuf, "one-sided spacing can't find an acceptable solution\n"); SPfrontEnd->IFerror( ERR_WARNING, errBuf, NIL(IFuid) ); *rFound = 0.0; *nFound = 0; return(E_PRIVATE); } nSpaces = (int)stepsInSpan( width, spacing, rWanted );/* Check to see whether a flat span is acceptable. */ if ( ABS(nSpaces*spacing - width) < 1.0e-3*spacing ) { *rFound = 1.0; *nFound = nSpaces; return( OK ); } else if ( ABS((nSpaces+1)*spacing - width) < 1.0e-3*spacing ) { *rFound = 1.0; *nFound = nSpaces + 1; return( OK ); }/* Too much error involved in flat span means we have to ramp up. */ rTemp1 = rTemp2 = rWanted; oneSideRatio( width, spacing, &rTemp1, nSpaces ); oneSideRatio( width, spacing, &rTemp2, nSpaces+1 ); if ( (rTemp1 == 0.0) && (rTemp2 == 0.0) ) { sprintf( errBuf, "one-sided spacing can't find an acceptable solution\n"); SPfrontEnd->IFerror( ERR_WARNING, errBuf, NIL(IFuid) ); *rFound = 0.0; *nFound = 0; return(E_PRIVATE); } else if (rTemp1 == 0.0) { *rFound = rTemp2; *nFound = nSpaces + 1; } else if (rTemp2 == 0.0) { *rFound = rTemp1; *nFound = nSpaces; } else if (ABS(rWanted-rTemp2) < 4.0*ABS(rWanted-rTemp1)) { *rFound = rTemp2; *nFound = nSpaces + 1; } else { *rFound = rTemp1; *nFound = nSpaces; } return(OK);}/* * Name: oneSideRatio * Purpose: Compute the unique ratio 'r' which satisfies the following * constraint: w = hs*(1-r^ns)/(1-r) * Formals: < I > w : width of a span * < I > hs: step at one end of the span * <I/O> argRatio: ratio found, contains initial guess at entry * < I > ns: number of spaces to use in the span * Returns: OK / E_PRIVATE * Users: oneSideSpacing, maxLimSpacing * Calls: error-message handler */static intoneSideRatio( w, hs, argRatio, ns )double w;double hs;double *argRatio;int ns;{ double funcLow, funcUpp, func; double ratLow, ratUpp, ratio = *argRatio; double dns = (double)ns; int i;/* Get lower bound on solution. */ ratLow = 0.0; funcLow = hs - w; if ((funcLow > 0.0) || ((funcLow < 0.0)&&(ns <= 1))) { *argRatio = 0.0; return(E_PRIVATE); }/* Find upper bound on solution. */ ratUpp = ratio; do { ratUpp += 0.2; funcUpp = hs*geomSum(ratUpp, dns) - 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) - w; if ((func == 0.0) || (ratUpp - ratLow < RAT_TOL)) break; funcLow = hs*geomSum(ratLow, dns) - 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: quadRoots * Purpose: Find real roots of a quadratic equation if they exist. * Formals: < I > a, b, c: coefficients in ax^2+bx+c * < O > rp: the root using the positive sqrt value * < O > rn: the root using the negative sqrt value * Returns: TRUE / FALSE * Users: general * Calls: sqrt */static intquadRoots( a, b, c, rp, rn )double a, b, c;double *rp, *rn;{ double d; /* Discriminant */ double f; /* Root factor */ if (a == 0.0) return(FALSE); if (b == 0.0) { d = -c/a; if (d >= 0.0) { *rn = - (*rp = sqrt(d)); } else { return(FALSE);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -