int dblhashLength(dblhash_ *h, unsigned int *length) { ReturnErrIf(h == NULL); ReturnErrIf(length == NULL); *length = h->records_count; return 0; }
int dblhashRemove(dblhash_ *h, char *key) { unsigned int code; record_ *recs; unsigned int off, ind, size; ReturnErrIf(h == NULL); ReturnErrIf(key == NULL); code = strhash(key); recs = h->records; size = sizes[h->size_index]; ind = code % size; off = 0; while (recs[ind].hash) { if ((code == recs[ind].hash) && (recs[ind].key != NULL)) { if(!strcmp(key, recs[ind].key)) { /* Do not erase hash, so probes for collisions succeed */ if((recs[ind].freeMem != 'n') && (recs[ind].key != NULL)) { free(recs[ind].key); } recs[ind].key = NULL; recs[ind].value = HUGE_VAL; h->records_count--; return 0; } } ind = (code + (int)pow(++off, 2)) % size; } ReturnErr("Couldn't find %s", key); }
int integratorInitialize(integrator_ *r, double ic, double *ydtdx) { int i; ReturnErrIf(r == NULL); ReturnErrIf(ydtdx == NULL); r->ydtdx = ydtdx; r->y0 = 0.0; r->dydx0 = 0.0; r->n = 0; for(i = 0; i < N; i++) { r->t[i] = 0.0; r->h[i] = r->control->tstop; r->y[i] = 0.0; r->f[i] = *ydtdx; r->x[i] = ic; r->f[i] = (*r->ydtdx); } if(r->units == 'V') { r->abstol = r->control->vntol; } else if(r->units == 'A') { r->abstol = r->control->abstol; } else if(r->units == 'F') { r->abstol = r->control->captol; } else { ReturnErr("Unsupported units type"); } return 0; }
int dblhashFindPtr(dblhash_ *h, char *key, double **value) { record_ *recs; unsigned int off, ind, size; unsigned int code; ReturnErrIf(h == NULL); ReturnErrIf(key == NULL); ReturnErrIf(value == NULL); code = strhash(key); recs = h->records; size = sizes[h->size_index]; ind = code % size; off = 0; /* search on hash which remains even if a record has been removed, * so hash_remove() does not need to move any collision records */ while (recs[ind].hash) { if ((code == recs[ind].hash) && (recs[ind].key != NULL)) { if(!strcmp(key, recs[ind].key)) { *value = &recs[ind].value; return 0; } } ind = (code + (int)pow(++off,2)) % size; } /* Couldn't find the key */ *value = NULL; return 0; }
int historyGetTime(history_ *r, double *time) { ReturnErrIf(r == NULL); ReturnErrIf(time == NULL); *time = r->time; return 0; }
static int dblhashGrow(dblhash_ *h) { int i; record_ *old_recs, *new_recs; unsigned int old_recs_length; Debug("Growing Hash %p", h); ReturnErrIf(h->size_index == (sizes_count - 1)); old_recs_length = sizes[h->size_index]; old_recs = h->records; new_recs = calloc(sizes[++h->size_index], sizeof(record_)); ReturnErrIf(new_recs == NULL); h->records = new_recs; h->records_count = 0; /* rehash table */ for (i=0; i < old_recs_length; i++) { if (old_recs[i].hash && old_recs[i].key) { ReturnErrIf(dblhashAdd(h, old_recs[i].key, old_recs[i].freeMem, old_recs[i].value)); } } free(old_recs); return 0; }
int historyRecall(history_ *r, double *data, int length) { ReturnErrIf(r == NULL); ReturnErrIf(data == NULL); ReturnErrIf(length != r->length); memcpy(data, r->data, length*sizeof(double)); return 0; }
int historyGetAllData(history_ *r, double *data, int length) { ReturnErrIf(r == NULL); ReturnErrIf(data == NULL); ReturnErrIf(length != (r->length + 1)); data[0] = r->time; memcpy(&data[1], r->data, r->length*sizeof(double)); return 0; }
int historyGetData(history_ *r, double *data, int index) { ReturnErrIf(r == NULL); ReturnErrIf(data == NULL); ReturnErrIf(index < 0); ReturnErrIf(index >= r->length); *data = r->data[index]; return 0; }
int integratorDestroy(integrator_ **r) { ReturnErrIf(r == NULL); ReturnErrIf((*r) == NULL); Debug("Destroying NI %p", (*r)); free(*r); *r = NULL; return 0; }
int integratorIntegrate(integrator_ *r, double x0, double *dydx0, double *y0) { double t0, mult; ReturnErrIf(r == NULL); ReturnErrIf(dydx0 == NULL); ReturnErrIf(y0 == NULL); ReturnErrIf(isnan(x0)); /* Only step time when time is increasing, the simulator can search back * in time for a more appropiate point (i.e. based on next step above) */ t0 = r->control->time; ReturnNaNIf(isnan(t0)); if(t0 > r->t[(r->n+1)%N]) { r->n++; } /* Set New Time */ r->h[r->n%N] = t0 - r->t[r->n%N]; r->t[(r->n+1)%N] = t0; /* Record X, Y, and F*/ r->x[r->n%N] = x0; r->y[r->n%N] = r->dydx0 * x0 - r->y0; r->f[r->n%N] = (*r->ydtdx); /* Calculate Next dydx0 and y0 Using Numerical Integration */ if(r->control->integratorOrder < 2) { /* Backward-Euler */ *dydx0 = r->f[(r->n-1)%N] / r->h[r->n%N]; *y0 = (*dydx0) * r->x[r->n%N]; } else { /* Trapazoidal */ *dydx0 = 2.0 * r->f[r->n%N] / r->h[r->n%N]; mult = r->f[r->n%N]/r->f[(r->n-1)%N]; if(isnan(mult)) { mult = 1/r->control->gmin; } /* y multiplier compensates for a changing function value, i.e. not your basic trapazoidal integration, refer to "Electronic Circuit and System Simulation Methods" by Pillage, Rohrer, and Visweswariah page 310 for more details */ *y0 = (*dydx0) * r->x[r->n%N] + mult*r->y[r->n%N]; } /* Store values for next time */ r->dydx0 = *dydx0; r->y0 = *y0; return 0; }
int devicePrint(device_ *r, void *data) { ReturnErrIf(r == NULL); ReturnErrIf(data != NULL); ReturnErrIf(r->class == NULL); if(r->class->print != NULL) { ReturnErrIf(r->class->print(r)); } return 0; }
int deviceIntegrate(device_ *r, void *data) { ReturnErrIf(r == NULL); ReturnErrIf(data != NULL); ReturnErrIf(r->class == NULL); if(r->class->integrate != NULL) { ReturnErrIf(r->class->integrate(r)); } return 0; }
int deviceLoad(device_ *r, void *data) { ReturnErrIf(r == NULL); ReturnErrIf(data != NULL); ReturnErrIf(r->class == NULL); if(r->class->load != NULL) { ReturnErrIf(r->class->load(r)); } return 0; }
int deviceInitStep(device_ *r, void *data) { ReturnErrIf(r == NULL); ReturnErrIf(data != NULL); ReturnErrIf(r->class == NULL); if(r->class->initStep != NULL) { ReturnErrIf(r->class->initStep(r)); } return 0; }
int checkbreakDestroy(checkbreak_ **r) { ReturnErrIf(r == NULL); ReturnErrIf((*r) == NULL); Debug("Destroying Break Check %p", *r); free(*r); *r = NULL; return 0; }
int calcDiff(calc_ *r, char *variable, double *solution) { tokenSolveArgs_ args; ReturnErrIf(r == NULL); ReturnErrIf(solution == NULL); ReturnErrIf(variable == NULL); args.parser = r->parser; args.solution = solution; ReturnErrIf(hashFind(r->variables, variable, (void*)&args.diffVariable)); ReturnErrIf(args.diffVariable == NULL, "Couldn't find variable %s.", variable); /* Put Parser in differentiation mode */ Debug("%s", ParseTokenName(TOKEN_DIFF)); Parse(r->parser, TOKEN_DIFF, NULL, solution); ReturnErrIf(isnan(*solution), "Parser failed"); ReturnErrIf(listExecute(r->tokens, (listExecute_)tokenSolve, &args)); ReturnErrIf(isnan(*solution), "Parser failed"); return 0; }
int waveformNextStep(waveform_ *r, double *nextStep) { double tp, time; ReturnErrIf(r == NULL); ReturnErrIf(nextStep == NULL); time = r->control->time; switch(r->type) { case 'p': /* pulse */ tp = fmod(time, *r->d.pulse.per); *nextStep = *r->d.pulse.td - tp; if(*nextStep > 0) break; *nextStep += *r->d.pulse.tr; if(*nextStep > 0) break; *nextStep += *r->d.pulse.pw; if(*nextStep > 0) break; *nextStep += *r->d.pulse.tf; if(*nextStep > 0) break; *nextStep = *r->d.pulse.per - tp; break; case 'g': /* gauss */ /* Should be a smooth waveform so don't expect break-points */ break; case 's': /* sin */ if(time < *r->d.sin.td) { *nextStep = *r->d.sin.td; } break; case 'e': /* exp */ if(time < *r->d.exp.td1) { *nextStep = *r->d.exp.td1 - time; } else if(time < *r->d.exp.td2) { *nextStep = *r->d.exp.td2 - time; } break; case 'l': /* pwl */ case 'c': /* pwc */ ReturnErrIf(piecewiseGetNextX(r->d.pw.pw, &r->d.pw.index, time, &tp)); if(tp != HUGE_VAL) { *nextStep = tp - time; } break; default: break; } return 0; }
int deviceStep(device_ *r, int *breakPoint) { int localBreakPoint = 0; ReturnErrIf(r == NULL); ReturnErrIf(breakPoint == NULL); ReturnErrIf(r->class == NULL); if(r->class->step != NULL) { ReturnErrIf(r->class->step(r, &localBreakPoint)); *breakPoint = (*breakPoint) || (localBreakPoint); } return 0; }
int deviceLinearize(device_ *r, int *linear) { int localLinear = 1; ReturnErrIf(r == NULL); ReturnErrIf(linear == NULL); ReturnErrIf(r->class == NULL); if(r->class->linearize != NULL) { ReturnErrIf(r->class->linearize(r, &localLinear)); *linear = (*linear) && (localLinear); } return 0; }
int calcSolve(calc_ *r, double *solution) { tokenSolveArgs_ args; ReturnErrIf(r == NULL); ReturnErrIf(solution == NULL); args.parser = r->parser; args.solution = solution; args.diffVariable = NULL; ReturnErrIf(listExecute(r->tokens, (listExecute_)tokenSolve, &args)); ReturnErrIf(isnan(*solution), "Parser failed"); return 0; }
int checkbreakIsBreak(checkbreak_ *r, double x) { ReturnErrIf(r == NULL); /* Only step time when time is increasing, the simulator can search back * in time for a more appropiate point (i.e. based on next step above) */ if(r->control->time > r->t[r->n%N]) { r->n++; } /* update x, t, and angle */ r->x[r->n%N] = x; r->t[r->n%N] = r->control->time; r->theta[r->n%N] = atan2(r->x[r->n%N] - r->x[(r->n-1)%N], r->t[r->n%N] - r->t[(r->n-1)%N]); if(fabs(r->theta[r->n%N] - r->theta[(r->n-1)%N]) > r->maxAngle) { Debug("Break at %e with angles %e,%e", r->t[r->n%N], r->theta[r->n%N], r->theta[(r->n-1)%N]); return 1; } return 0; }
int checkbreakInitialize(checkbreak_ *r, double ic) { int i; ReturnErrIf(r == NULL); /* Make a local copy, this allows the control value to be changed between runs */ if(r->units == 'V') { r->maxAngle = r->control->maxAngleV; } else if(r->units == 'A') { r->maxAngle = r->control->maxAngleA; } else { ReturnErr("Unsupported unit type %c, should be 'A' or 'V'", r->units); } for(i = 0; i < N; i++) { r->x[i] = ic; r->t[i] = 0.0; } r->n = 0; return 0; }
int integratorNextStep(integrator_ *r, double x0, double *h) { double y0, ey = 0.0, eyp, e, dd; ReturnErrIf(r == NULL); ReturnErrIf(h == NULL); ReturnErrIf(isnan(x0)); y0 = r->dydx0 * x0 - r->y0; /* Calculate y error */ ey = r->control->reltol * MaxAbs(r->y[r->n%N], y0) + r->abstol; /* Calculate y' error */ eyp = r->control->reltol * MaxAbs(MaxAbs(x0, r->x[r->n%N]) * (*r->ydtdx / r->h[r->n%N]), r->control->chgtol); e = MaxAbs(eyp, ey); /* Calculate Estimated Error of Numerical Intergration */ if(r->control->integratorOrder < 2) { /* Backward-Euler */ dd = DD2(((*r->ydtdx) * x0), (r->f[r->n%N] * r->x[r->n%N]), (r->f[(r->n-1)%N] * r->x[(r->n-1)%N]), r->h[r->n%N], r->h[(r->n-1)%N]); dd *= 1.0/2.0; *h = r->control->trtol * e / MaxAbs(dd , r->abstol); } else { /* Trapazoidal */ dd = DD3(((*r->ydtdx) * x0), (r->f[r->n%N] * r->x[(r->n)%N]), (r->f[(r->n-1)%N] * r->x[(r->n-1)%N]), (r->f[(r->n-2)%N] * r->x[(r->n-2)%N]), r->h[r->n%N], r->h[(r->n-1)%N], r->h[(r->n-2)%N]); /* See page 309 of "The Spice Book" */ dd *= 1.0/12.0; *h = sqrtf(r->control->trtol * e / MaxAbs(dd , r->abstol)); } Debug("h = %e, e = %e, dd = %e", *h, e, dd); ReturnErrIf(isnan(*h)); return 0; }
int deviceMinStep(device_ *r, double *minStep) { double localMinStep = 0.0; ReturnErrIf(r == NULL); ReturnErrIf(minStep == NULL); ReturnErrIf(r->class == NULL); if(r->class->minStep != NULL) { ReturnErrIf(r->class->minStep(r, &localMinStep)); if((localMinStep > 0.0) && (localMinStep < *minStep)) { *minStep = localMinStep; } } return 0; }
int deviceNextStep(device_ *r, double *nextStep) { double localNextStep = 0.0; ReturnErrIf(r == NULL); ReturnErrIf(nextStep == NULL); ReturnErrIf(r->class == NULL); if(r->class->nextStep != NULL) { ReturnErrIf(r->class->nextStep(r, &localNextStep)); if((localNextStep > r->control->minstep) && (localNextStep < *nextStep)) { *nextStep = localNextStep; } } return 0; }
int waveformDestroy(waveform_ **r) { ReturnErrIf(r == NULL); ReturnErrIf((*r) == NULL); Debug("Destroying Waveform %p", *r); if((((*r)->type == 'l') || ((*r)->type == 'c')) && ((*r)->d.pw.pw != NULL)) { if(piecewiseDestroy(&(*r)->d.pw.pw)) { Warn("Error destroying piecewise"); } } free(*r); *r = NULL; return 0; }
int dblhashFind(dblhash_ *h, char *key, double *value) { double *valuePtr; ReturnErrIf(dblhashFindPtr(h, key, &valuePtr)); if(valuePtr != NULL) { *value = *valuePtr; } else { *value = HUGE_VAL; } return 0; }
int historyDestroy(history_ *r) { ReturnErrIf(r == NULL); if(r->data != NULL) { free(r->data); } free(r); return 0; }
int dblhashDestroy(dblhash_ **h) { int i; ReturnErrIf(h == NULL); ReturnErrIf((*h) == NULL); Debug("Destroying Hash %p", *h); if((*h)->records != NULL) { for(i = 0; i < sizes[(*h)->size_index]; i++) { if(((*h)->records[i].freeMem != 'n') && ((*h)->records[i].key != NULL)) { free((*h)->records[i].key); } } free((*h)->records); } free(*h); *h = NULL; return 0; }