You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

178 lines
5.3 KiB

/**********
Copyright 1991 Regents of the University of California. All rights reserved.
Author: 1991 David A. Gates, U. C. Berkeley CAD Group
Modifed: 2001 Paolo Nenzi
**********/
#include "ngspice/ngspice.h"
#include "ngspice/cktdefs.h"
#include "ngspice/numenum.h"
#include "ngspice/domndefs.h"
#include "ngspice/material.h"
#include "ngspice/meshext.h"
#include "ngspice/gendev.h"
#include "ngspice/sperror.h"
#include "ngspice/suffix.h"
extern int DOMNcheck( DOMNcard *, MATLmaterial * );
extern int DOMNsetup( DOMNcard *, DOMNdomain **, MESHcoord *, MESHcoord *,
MATLmaterial * );
/*
* Name: DOMNcheck
* Purpose: checks a list of DOMNcards for input errors
* Formals: cardList: the list to check
* Returns: OK/E_PRIVATE
* Users: numerical device setup routines
* Calls: error message handler
*/
int
DOMNcheck(DOMNcard *cardList, MaterialInfo *matlList)
{
DOMNcard *card;
MATLmaterial *matl;
int cardNum = 0;
int error = OK;
for ( card = cardList; card != NULL; card = card->DOMNnextCard ) {
cardNum++;
if (card->DOMNxLowGiven && card->DOMNixLowGiven) {
SPfrontEnd->IFerrorf( ERR_INFO, "domain card %d uses both location and index - location ignored", cardNum );
card->DOMNxLowGiven = FALSE;
}
if (card->DOMNxHighGiven && card->DOMNixHighGiven) {
SPfrontEnd->IFerrorf( ERR_INFO, "domain card %d uses both location and index - location ignored", cardNum );
card->DOMNxHighGiven = FALSE;
}
if (card->DOMNyLowGiven && card->DOMNiyLowGiven) {
SPfrontEnd->IFerrorf( ERR_INFO, "domain card %d uses both location and index - location ignored", cardNum );
card->DOMNyLowGiven = FALSE;
}
if (card->DOMNyHighGiven && card->DOMNiyHighGiven) {
SPfrontEnd->IFerrorf( ERR_INFO, "domain card %d uses both location and index - location ignored", cardNum );
card->DOMNyHighGiven = FALSE;
}
if (!card->DOMNmaterialGiven) {
SPfrontEnd->IFerrorf( ERR_WARNING, "domain card %d is missing a material index", cardNum );
error = E_PRIVATE;
} else {
/* Make sure the material exists */
for ( matl = matlList; matl != NULL; matl = matl->next ) {
if ( card->DOMNmaterial == matl->id ) {
break;
}
}
if (matl == NULL) {
SPfrontEnd->IFerrorf( ERR_WARNING, "domain card %d specifies a non-existent material", cardNum );
error = E_PRIVATE;
}
}
if (!card->DOMNnumberGiven) {
SPfrontEnd->IFerrorf( ERR_WARNING, "domain card %d is missing an ID number", cardNum );
error = E_PRIVATE;
}
/* Return now if anything has failed */
if (error) return(error);
}
return(OK);
}
/*
* Name: DOMNsetup
* Purpose: convert a list of DOMNcard's to DOMNdomain's
* Formals: cardList: list of cards to setup
* domainList: returns the list of DOMNdomain's
* xMeshList: list of coordinates in the x mesh
* yMeshList: list of coordinates in the y mesh
* Returns: OK/E_PRIVATE
* Users: numerical devices
* Calls: DOMNcheck
*/
int
DOMNsetup(DOMNcard *cardList, DOMNdomain **domainList, MESHcoord *xMeshList,
MESHcoord *yMeshList, MaterialInfo *materialList)
{
DOMNcard *card;
DOMNdomain *newDomain = NULL;
int ixMin, ixMax, iyMin, iyMax;
int cardNum = 0;
int error;
/* Initialize list of domains */
*domainList = NULL;
/* Check the card list */
if ((error = DOMNcheck( cardList, materialList )) != 0) return( error );
/* Find the limits on the indices */
MESHiBounds( xMeshList, &ixMin, &ixMax );
MESHiBounds( yMeshList, &iyMin, &iyMax );
error = OK;
for ( card = cardList; card != NULL; card = card->DOMNnextCard ) {
cardNum++;
if (*domainList == NULL) {
RALLOC( newDomain, DOMNdomain, 1 );
*domainList = newDomain;
} else {
RALLOC( newDomain->next, DOMNdomain, 1 );
newDomain = newDomain->next;
}
newDomain->id = card->DOMNnumber;
newDomain->material = card->DOMNmaterial;
newDomain->next = NULL;
if (card->DOMNixLowGiven) {
newDomain->ixLo = MAX(card->DOMNixLow, ixMin);
}
else if (card->DOMNxLowGiven) {
newDomain->ixLo = MESHlocate( xMeshList, card->DOMNxLow );
}
else {
newDomain->ixLo = ixMin;
}
if (card->DOMNixHighGiven) {
newDomain->ixHi = MIN(card->DOMNixHigh, ixMax);
}
else if (card->DOMNxHighGiven) {
newDomain->ixHi = MESHlocate( xMeshList, card->DOMNxHigh );
}
else {
newDomain->ixHi = ixMax;
}
if (newDomain->ixLo > newDomain->ixHi) {
SPfrontEnd->IFerrorf( ERR_WARNING, "domain card %d has low x index (%d) > high x index (%d)", cardNum, newDomain->ixLo, newDomain->ixHi );
error = E_PRIVATE;
}
if (card->DOMNiyLowGiven) {
newDomain->iyLo = MAX(card->DOMNiyLow, iyMin);
}
else if (card->DOMNyLowGiven) {
newDomain->iyLo = MESHlocate( yMeshList, card->DOMNyLow );
}
else {
newDomain->iyLo = iyMin;
}
if (card->DOMNiyHighGiven) {
newDomain->iyHi = MIN(card->DOMNiyHigh, iyMax);
}
else if (card->DOMNyHighGiven) {
newDomain->iyHi = MESHlocate( yMeshList, card->DOMNyHigh );
}
else {
newDomain->iyHi = iyMax;
}
if (newDomain->iyLo > newDomain->iyHi) {
SPfrontEnd->IFerrorf( ERR_WARNING, "domain card %d has low y index (%d) > high y index (%d)", cardNum, newDomain->iyLo, newDomain->iyHi );
error = E_PRIVATE;
}
}
return( error );
}