1 #ifndef _SPARAMETERBLOCK_HPP_INC_
2 #define _SPARAMETERBLOCK_HPP_INC_
12 #include <immintrin.h>
54 const size_t length(
size_t a,
size_t b)
const {
62 const size_t offset(
size_t a,
size_t b)
const {
66 T &
data(
size_t a,
size_t b,
size_t n) {
70 const T &
data(
size_t a,
size_t b,
size_t n)
const {
74 T &
time(
size_t a,
size_t b,
size_t n) {
78 const T &
time(
size_t a,
size_t b,
size_t n)
const {
89 std::vector<SParameterPort<T> >
port;
107 const size_t n, T sTimePoint,
const T simulationTimestep,
108 size_t sizeG_A)
const {
109 T kprime = sTimePoint / simulationTimestep;
117 T index = n - kprime;
124 size_t floor =
static_cast<size_t>(index);
125 if (floor <= 0 || floor + 1 >= n) {
129 T mix = index -
static_cast<T
>(floor);
136 if (
port[portIndex].positive != 0) {
137 uppArr[0] = solutionMatrix(
port[portIndex].positive - 1, floor + 1);
138 lowArr[0] = solutionMatrix(
port[portIndex].positive - 1, floor);
141 if (
port[portIndex].negative != 0) {
142 uppArr[1] = solutionMatrix(
port[portIndex].negative - 1, floor + 1);
143 lowArr[1] = solutionMatrix(
port[portIndex].negative - 1, floor);
146 uppArr[2] = solutionMatrix(sizeG_A +
port[portIndex].current - 1, floor + 1);
147 lowArr[2] = solutionMatrix(sizeG_A +
port[portIndex].current - 1, floor);
149 toRet = (uppArr[0] - lowArr[0]) * mix + lowArr[0] -
150 (uppArr[1] - lowArr[1]) * mix - lowArr[1] +
151 ((uppArr[2] - lowArr[2]) * mix + lowArr[2]) *
z_ref;
167 T simulationTimestep,
size_t sizeG_A)
const {
174 for (
size_t c = 0; c <
port.size(); c++) {
177 for (
size_t k = 1;
k <
s.length(p, c);
k++) {
179 simulationTimestep, sizeG_A) *
195 for (
size_t p = 0; p <
port.size(); p++) {
196 size_t np =
port[p].positive - 1;
197 size_t nn =
port[p].negative - 1;
198 size_t curr =
port[p].current - 1;
201 if (
port[p].positive != 0) {
202 stamp.
G(stamp.
sizeG_A + curr, np) += 1;
203 stamp.
G(np, stamp.
sizeG_A + curr) += 1;
206 if (
port[p].negative != 0) {
207 stamp.
G(stamp.
sizeG_A + curr, nn) += -1;
208 stamp.
G(nn, stamp.
sizeG_A + curr) += -1;
211 for (
size_t c = 0; c <
port.size(); c++) {
213 T alpha =
port[p].beta *
port[p].s0[c];
214 if (
port[c].positive != 0) {
216 port[c].positive - 1) += -alpha;
218 if (
port[c].negative != 0) {
219 stamp.
G(stamp.
sizeG_A + curr,
port[c].negative - 1) += alpha;
229 const size_t currentSolutionIndex,
230 T simulationTimestep)
const {
231 for (
size_t p = 0; p <
port.size(); p++) {
232 size_t curr =
port[p].current - 1;
235 0) +=
V_p(p, solutionMatrix, currentSolutionIndex,
236 simulationTimestep, stamp.
sizeG_A);
241 size_t numCurrents)
const {
242 for (
size_t p = 0; p <
port.size(); p++) {
243 size_t np =
port[p].positive - 1;
244 size_t nn =
port[p].negative - 1;
245 size_t curr =
port[p].current - 1;
249 for (
size_t k = 0;
k <
s.length(p, p);
k++) {
250 sppSum +=
s.data(p, p,
k);
252 T Rprime =
port[p].beta *
z_ref * (1 + sppSum) /
253 (1 -
port[p].beta * sppSum);
255 if (
port[p].positive != 0) {
256 stamp.
G(stamp.
sizeG_A + curr, np) += 1;
257 stamp.
G(np, stamp.
sizeG_A + curr) += 1;
260 if (
port[p].negative != 0) {
261 stamp.
G(stamp.
sizeG_A + curr, nn) += -1;
262 stamp.
G(nn, stamp.
sizeG_A + curr) += -1;
266 for (
size_t c = 0; c <
port.size(); c++) {
268 T alpha =
port[p].beta *
port[p].s0[c];
271 for (
size_t k = 0;
k <
s.length(p, c);
k++) {
272 alphaPrime +=
s.data(p, c,
k);
275 alphaPrime =
port[p].beta * alphaPrime;
279 alphaPrime = alphaPrime / (1 -
port[p].beta * sppSum);
282 if (
port[c].positive != 0) {
284 port[c].positive - 1) += -alphaPrime;
286 if (
port[c].negative != 0) {
288 port[c].negative - 1) += alphaPrime;
291 1) += -
z_ref * alphaPrime;
300 const size_t currentSolutionIndex, T timestep,
309 using CT = std::complex<T>;
310 using FSP = std::vector<CT>;
313 std::vector<T> freqs;
314 std::vector<std::vector<FSP> > freqSParams(
s.numPorts);
318 while (file.peek() ==
'#' || file.peek() ==
'!') {
319 std::getline(file, line);
324 while (!file.eof()) {
329 freqs.emplace_back(val1);
330 for (
size_t a = 0;
a <
s.numPorts;
a++) {
331 freqSParams[
a].resize(
s.numPorts);
334 for (
size_t b = 0;
b <
s.numPorts;
b++) {
335 for (
size_t a = 0;
a <
s.numPorts;
a++) {
336 file >> val1 >> val2;
337 freqSParams[
a][
b].emplace_back(val1, val2);
350 s.sParamLengthOffset.resize(
s.numPorts *
s.numPorts);
351 for (
size_t a = 0;
a <
s.numPorts;
a++) {
352 port[
a].s0.resize(
s.numPorts);
353 for (
size_t b = 0;
b <
s.numPorts;
b++) {
356 T thresholdToKeep = 1;
357 for (
auto entry : causal.data) {
358 thresholdToKeep = std::max(
std::abs(entry), thresholdToKeep);
363 s.offset(
a,
b) =
s._data.size();
364 for (
size_t n = 0; n < causal.data.size(); n++) {
365 if (n == 0 ||
std::abs(causal.data[n]) > thresholdToKeep) {
366 s._data.emplace_back(causal.data[n]);
367 s._time.emplace_back(n == 0 ? 0
368 : n * causal.Ts - causal.tau);
369 std::cout <<
s._time.back() <<
" " <<
s._data.back()
373 s.length(
a,
b) =
s._data.size() -
s.offset(
a,
b);
374 std::cout <<
"Pruned " << ((2 * freqs.size() - 2) -
s.length(
a,
b))
375 <<
" DTIR entries out of " << (2 * freqs.size() - 2)
376 <<
" less than " << thresholdToKeep <<
" ("
381 port[
a].beta = 1.0 / (1 -
s.data(
a,
a, 0));
388 size_t & numNodes,
size_t & numCurrents,
size_t & numDCCurrents) {
390 std::regex SParameterBlockInitialRegex =
generateRegex(
"S",
"w n s",
true,
393 std::regex_search(line, matches, SParameterBlockInitialRegex);
402 size_t numPorts = std::stoul(matches.str(3));
403 block.
s.numPorts = numPorts;
404 block.
port = std::vector<SParameterPort<T> >(numPorts);
406 auto strIter = matches.suffix().first;
407 std::regex SParameterBlockPortRegex(R
"(^(\d+?)\s(\d+?)\s)");
408 for (
size_t p = 0; p < numPorts; p++) {
409 std::regex_search(strIter, line.cend(), matches,
410 SParameterBlockPortRegex);
411 block.
port[p].positive = std::stoi(matches.str(1));
412 block.
port[p].negative = std::stoi(matches.str(2));
414 numNodes = std::max(numNodes, std::stoull(matches.str(1)));
415 numNodes = std::max(numNodes, std::stoull(matches.str(2)));
417 block.
port[p].current = ++numCurrents;
419 strIter = matches.suffix().first;
421 std::regex endOfLineRegex(R
"(^(.*)$)");
422 std::regex_search(strIter, line.cend(), matches, endOfLineRegex);
426 elements.dynamicElements.emplace_back(
428 for (
size_t p = 0; p < numPorts; p++) {
430 {{block.
port[p].positive,
elements.dynamicElements.back()},
431 {block.
port[p].negative,
elements.dynamicElements.back()}});
std::regex generateRegex(std::string indentifier, std::string simplifiedMatching, bool startAnchor=true, bool endAnchor=true)
a helper function to aid in the construction of regexes for parsing netlist files
ForceCausal::CausalData< T > forceCausal(const std::vector< T > &freq, const std::vector< std::complex< T > > &data)
common weighting for all matrix elements
Find a complex rational model for freq domain data for a
end if abs(real(dotprod))>rstoerst rstoerst
a glorified container for the different types of components.
A template base class to define the fundamental things a component should define.
std::string designator
The designator as in the netlist for e.g.
A matrix class with support for LU-decomposition, and left division.
A DTIR based model of an s-parameter block.
SParameterSequence< T > s
void addDCAnalysisStampTo(Stamp< T > &stamp, const Matrix< T > &solutionVector, size_t numCurrents) const
adds this component's DC stamp to the target stamp.
T aWaveConvValue(size_t portIndex, const Matrix< T > &solutionMatrix, const size_t n, T sTimePoint, const T simulationTimestep, size_t sizeG_A) const
performs a linear interpolation and returns the a wave value for use in the convolution.
T V_p(size_t p, const Matrix< T > &solutionMatrix, const size_t n, T simulationTimestep, size_t sizeG_A) const
Determines the equivalent port voltage source by convolving the (historic) a wave values with the DTI...
void addStaticStampTo(Stamp< T > &stamp) const
Adds this component's static stamp to the target stamp.
void readInTouchstoneFile()
reads in the s-parameter data from a touchstone file. Currently it ignores the units of frequency,...
void addDynamicStampTo(Stamp< T > &stamp, const Matrix< T > &solutionMatrix, const size_t currentSolutionIndex, T simulationTimestep) const
Adds this component's dynamic stamp to the target stamp.
static void addToElements(const std::string &line, CircuitElements< T > &elements, size_t &numNodes, size_t &numCurrents, size_t &numDCCurrents)
std::vector< SParameterPort< T > > port
std::string touchstoneFilePath
void updateStoredState(const Matrix< T > &solutionMatrix, const size_t currentSolutionIndex, T timestep, size_t sizeG_A)
Updates any stored state based on the current solution index.
a helper struct to store the information for the ports of an S-Parameter Block
T R
The equivalent resistance.
size_t negative
The negative index.
size_t current
The current index.
size_t positive
The positive index.
std::vector< T > s0
The start of each SParameterSequence.
a helper struct to store the DTIR sequence for the bloc
size_t & length(size_t a, size_t b)
const size_t offset(size_t a, size_t b) const
const T & data(size_t a, size_t b, size_t n) const
const T & time(size_t a, size_t b, size_t n) const
std::vector< SParamLengthOffset > sParamLengthOffset
T & data(size_t a, size_t b, size_t n)
T & time(size_t a, size_t b, size_t n)
const size_t length(size_t a, size_t b) const
size_t & offset(size_t a, size_t b)
A helper struct to store the preallocated stamps for MNA.