📄 meshset.c
字号:
/**********Copyright 1991 Regents of the University of California. All rights reserved.Author: 1991 David A. Gates, U. C. Berkeley CAD Group**********//**********Mesh Setup & Query Routines.**********//* Imports */#include "spice.h"#include <stdio.h>#include <math.h>#include "const.h"#include "util.h"#include "cktdefs.h"#include "nummacs.h"#include "meshdefs.h"#include "meshext.h"#include "gendev.h"#include "sperror.h"#include "suffix.h"/* Local Constants */#define CMP_TOL 1.0e-9 /* Tolerance on (double) comparisons */#define RAT_TOL 1.0e-6 /* Error allowed in ratio calc's */#define RAT_LIM 50 /* Maximum number of ratio iterations */#define UM_TO_CM 1.0e-4 /* Micron to centimeter conversion *//* Forward Declarations */#ifdef __STDC__static int oneSideSpacing( double, double, double, double *, int * );static int twoSideSpacing( double, double, double, double, double *, double *, int *, int * );static int maxLimSpacing( double, double, double, double, double *, int *, int * );static int oneSideRatio( double, double, double *, int );static int twoSideRatio( double, double, double, double *, int, int );#elsestatic int oneSideSpacing();static int twoSideSpacing();static int maxLimSpacing();static int oneSideRatio();static int twoSideRatio();#endif/* END OF HEADER *//* * Name: MESHmkArray * Purpose: Turn a coordinate list into a coordinate array. * Formals: < I > coordList: a sorted list of all the coordinates * < I > numCoords: the length of the listi, if 0 find it * Returns: a (double) array of those coordinates, with length in a[0] * Users: routines used to create the final mesh * Calls: (none) */double *MESHmkArray( coordList, numCoords )MESHcoord *coordList;int numCoords;{ double *array; MESHcoord *coord; if ( numCoords <= 0 ) { numCoords = 0; for ( coord = coordList; coord != NIL(MESHcoord); coord = coord->next ) { numCoords++; } } if ( numCoords != 0 ) { XALLOC( array, double, 1 + numCoords ); numCoords = 0; array[ 0 ] = (double) numCoords; numCoords = 1; for ( coord = coordList; coord != NIL(MESHcoord); coord = coord->next ) { array[ numCoords++ ] = coord->location; } return array; } else { return NIL(double); } /* NOTREACHED */}/* * Name: MESHiBounds * Purpose: Find the minimum and maximum indices in a mesh list. * Formals: < I > coordList: a sorted list of all the coordinates * < O > ixMin: the minimum index * < O > ixMax: the maximum index * Returns: (none) * Users: routines wanting to fine the ends of a mesh * Calls: (none) */voidMESHiBounds( coordList, ixMin, ixMax )MESHcoord *coordList;int *ixMin, *ixMax;{ MESHcoord *last; if (coordList) { *ixMin = coordList->number; for ( last = coordList; last->next != NIL(MESHcoord); last = last->next ); *ixMax = last->number; } else { *ixMin = *ixMax = -1; }}/* * Name: MESHlBounds * Purpose: Find the minimum and maximum locations in a mesh list. * Formals: < I > coordList: a sorted list of all the coordinates * < O > lcMin: the minimum location * < O > lcMax: the maximum location * Returns: (none) * Users: routines wanting to find the ends of a mesh * Calls: (none) */voidMESHlBounds( coordList, lcMin, lcMax )MESHcoord *coordList;double *lcMin, *lcMax;{ MESHcoord *last; if (coordList) { *lcMin = coordList->location; for ( last = coordList; last->next != NIL(MESHcoord); last = last->next ); *lcMax = last->location; } else { *lcMin = *lcMax = 0.0; }}/* * Name: MESHlocate * Purpose: Finds the index of the MESHcoord nearest to a location. * Formals: < I > coordList: a sorted list of all available coordinates * < I > location: the location to find * Returns: index / -1 (list empty) * Users: routines that convert distances to indices * Calls: (none) */intMESHlocate( coordList, location )MESHcoord *coordList;double location;{ MESHcoord *coord, *prevCoord = NIL(MESHcoord); int index;/* Find the coordinates which flank the location. */ for ( coord = coordList; coord != NIL(MESHcoord); coord = coord->next ) { if ( coord->location > location ) break; prevCoord = coord; }/* Get the index. */ if (prevCoord && coord) { if ( location <= (prevCoord->location + coord->location) / 2.0 ) { index = prevCoord->number; } else { index = coord->number; } } else if ( coord ) { index = coord->number; } else if ( prevCoord ) { index = prevCoord->number; } else { index = -1; } return( index );}/* * Name: MESHcheck * Purpose: Checks a list of mesh cards for input errors. * Formals: <I/O> cardList: pointer to head of linked list of MESHcard's * < I > dim: 'x', 'y' or 'z' dimension * Returns: OK / E_PRIVATE * Users: setup routines * Calls: error-message handler */intMESHcheck( dim, cardList )char dim;MESHcard *cardList;{ register MESHcard *card; int cardNum = 0; double locStart = 0.0, locEnd; double ratio; int error = OK; char errBuf[512]; if ( cardList == NIL(MESHcard) ) { sprintf( errBuf, "%c.mesh card list is empty", dim ); SPfrontEnd->IFerror( ERR_FATAL, errBuf, NIL(IFuid) ); locEnd = locStart; return( E_PRIVATE ); } for ( card = cardList; card != NIL(MESHcard); card = card->MESHnextCard ) { cardNum++;/* Am I trying to find number of nodes directly & indirectly? */ if (card->MESHnumberGiven && card->MESHratioGiven) { sprintf( errBuf, "%c.mesh card %d uses both number and ratio - number ignored", dim, cardNum ); SPfrontEnd->IFerror( ERR_INFO, errBuf, NIL(IFuid) ); card->MESHnumberGiven = FALSE; }/* Will I be able to locate endpoints? */ if (!card->MESHlocationGiven && !card->MESHwidthGiven) { sprintf( errBuf, "%c.mesh card %d has no distances", dim, cardNum ); SPfrontEnd->IFerror( ERR_FATAL, errBuf, NIL(IFuid) ); locEnd = locStart; error = E_PRIVATE; } else if (card->MESHlocationGiven && card->MESHwidthGiven) { sprintf( errBuf, "%c.mesh card %d uses both location and width - location ignored", dim, cardNum ); SPfrontEnd->IFerror( ERR_INFO, errBuf, NIL(IFuid) ); card->MESHlocationGiven = FALSE; locEnd = locStart + card->MESHwidth; } else if (card->MESHlocationGiven) { locEnd = card->MESHlocation; if (cardNum == 1) locStart = locEnd; } else { locEnd = locStart + card->MESHwidth; }/* Are the endpoints in the wrong order? */ if ( locEnd - locStart < - CMP_TOL ) { sprintf( errBuf, "%c.mesh card %d uses negative width", dim, cardNum ); SPfrontEnd->IFerror( ERR_FATAL, errBuf, NIL(IFuid) ); error = E_PRIVATE; }/* Are the endpoints too close together? */ else if ( (locEnd - locStart <= CMP_TOL) ) { if ( !(cardNum == 1 && locStart == locEnd) ) { sprintf( errBuf, "%c.mesh card %d has negligible width - ignored", dim, cardNum ); SPfrontEnd->IFerror( ERR_INFO, errBuf, NIL(IFuid) ); locStart = locEnd; } }/* Is the ratio out of the acceptable range? */ if (card->MESHratioGiven) { ratio = card->MESHratio; } else { ratio = 1.0; } if ((ratio < 1.0) || (ratio > 10.0)) { sprintf( errBuf, "%c.mesh card %d has ratio out of range - reset to 1.0", dim, cardNum ); SPfrontEnd->IFerror( ERR_INFO, errBuf, NIL(IFuid) ); ratio = 1.0; }/* Check sizes of h.start, h.end and h.max. */ if ((card->MESHhStartGiven && (card->MESHhStart <= 0.0)) || (card->MESHhEndGiven && (card->MESHhEnd <= 0.0)) || (card->MESHhMaxGiven && (card->MESHhMax <= 0.0))) { sprintf( errBuf, "%c.mesh card %d wants to use a non-positive spacing", dim, cardNum ); SPfrontEnd->IFerror( ERR_FATAL, errBuf, NIL(IFuid) ); error = E_PRIVATE; }/* Is the max spacing being used improperly? */ if (card->MESHhMaxGiven && ( ( card->MESHhStartGiven && card->MESHhEndGiven) || (!card->MESHhStartGiven && !card->MESHhEndGiven))) { sprintf( errBuf, "%c.mesh card %d needs to use one of h.start or h.end with h.max", dim, cardNum ); SPfrontEnd->IFerror( ERR_FATAL, errBuf, NIL(IFuid) ); error = E_PRIVATE; } else if (card->MESHhMaxGiven && card->MESHhStartGiven) { if (card->MESHhStart > card->MESHhMax) { sprintf( errBuf, "%c.mesh card %d wants h.start > h.max", dim, cardNum ); SPfrontEnd->IFerror( ERR_FATAL, errBuf, NIL(IFuid) ); error = E_PRIVATE; } else { card->MESHhEnd = card->MESHhMax; } } else if (card->MESHhMaxGiven && card->MESHhEndGiven) { if (card->MESHhEnd > card->MESHhMax) { sprintf( errBuf, "%c.mesh card %d wants h.end > h.max", dim, cardNum ); SPfrontEnd->IFerror( ERR_FATAL, errBuf, NIL(IFuid) ); error = E_PRIVATE; } else { card->MESHhStart = card->MESHhMax; } }/* Return now if anything has failed. */ if (error) return(error);/* Note: at this point we still aren't sure whether node numbers are OK. *//* Fill-in newly computed information. */ card->MESHlocStart = locStart; card->MESHlocEnd = locEnd; card->MESHratio = ratio;/* Advance current location. */ locStart = locEnd; } return(OK);}/* * Name: geomSum * Purpose: Computes the sum of n terms of a geometric series. * Formals: < I > r: ratio of one term to the next * < I > n: number of terms to sum * Returns: sum / 0.0 * Users: spacing routines * Calls: pow */static doublegeomSum( r, n )double r;double n;{ double sum; if ((r < 0.0) || (n <= 0.0)) { sum = 0.0; } else if (r == 0.0) { sum = 1.0; } else { if (ABS(r - 1.0) < 1.0e-4) { sum = n * (1.0 + (n - 1.0)*(r - 1.0)/2.0); } else { sum = (1.0 - pow(r,n))/(1.0 - r); } } return( sum );}/* * Name: addCoord * Purpose: add a new coordinate to the tail of a linked list * Formals: <I/O> head: head of linked list * <I/O> tail: tail of linked list * < I > number: node number of coordinate * < I > location: location of coordinate * Returns: OK / E_NOMEM * Users: MESHsetup * Calls: memory allocator */static intaddCoord( head, tail, number, location )MESHcoord **head, **tail;int number;double location;{ MESHcoord *newCoord; if (*head == NIL(MESHcoord)) { RALLOC( *tail, MESHcoord, 1 ); newCoord = *head = *tail; } else { RALLOC( (*tail)->next, MESHcoord, 1 ); newCoord = *tail = (*tail)->next; } newCoord->next = NIL(MESHcoord); newCoord->number = number; newCoord->location = location * UM_TO_CM; return(OK);}/* * Name: MESHsetup * Purpose: Converts a list of input MESHcard's to a list of MESHcoord's. * Expansion is performed so that node numbers in the final list * increase by one from coordinate to coordinate. The list * will grow until the input ends or a bad card is found. * Formals: < I > dim: 'x', 'y', or 'z' dimension * <I/O> cardList: the list of input cards * < O > coordList: the final list of coordinates * < O > numCoords: the number of coords in coordList * Returns: OK / E_PRIVATE * Users: numerical device setup routines * Calls: MESHcheck, MESHspacing, error-message handler */intMESHsetup( dim, cardList, coordList, numCoords )char dim;MESHcard *cardList;MESHcoord **coordList;int *numCoords;{ register MESHcard *card; MESHcoord *endCoord; int cardNum = 0; int i, totCoords, numStart=1, numEnd, nspStart, nspEnd, nspMax, nspLeft; double locStart, locEnd, location, space;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -