From 63a9b7024ec0bdb4cd2afe73f83df01e752f0e0b Mon Sep 17 00:00:00 2001 From: Carl Philipp Klemm <philipp@uvos.xyz> Date: Fri, 19 Jan 2024 13:53:29 +0100 Subject: [PATCH] improve documentation some more --- CMakeLists.txt | 4 + README.md | 2 - doc/CompiledExecution.pdf | Bin 0 -> 12322 bytes doc/DirectExecution.pdf | Bin 0 -> 12401 bytes doc/TorchExecution.pdf | Bin 0 -> 12828 bytes doc/_r-c_r.pdf | Bin 0 -> 2170 bytes doc/libeisgenerator.doxygen.in | 4 +- doc/mainpage.md.in | 9 +- doc/modelspage.md.in | 20 ++-- doc/r-c.pdf | Bin 0 -> 1839 bytes doc/r-rc.pdf | Bin 0 -> 2123 bytes doc/rc.pdf | Bin 0 -> 1994 bytes doc/readme.md.in | 3 + eisgenerator/basicmath.h | 103 ++++++++-------- eisgenerator/eistype.h | 209 +++++++++++++++++---------------- eisgenerator/log.h | 34 ++++-- eisgenerator/model.h | 149 ++++++++++++----------- eisgenerator/normalize.h | 23 ++-- eisgenerator/translators.h | 46 ++++---- 19 files changed, 332 insertions(+), 274 deletions(-) create mode 100644 doc/CompiledExecution.pdf create mode 100644 doc/DirectExecution.pdf create mode 100644 doc/TorchExecution.pdf create mode 100644 doc/_r-c_r.pdf create mode 100644 doc/r-c.pdf create mode 100644 doc/r-rc.pdf create mode 100644 doc/rc.pdf create mode 100644 doc/readme.md.in diff --git a/CMakeLists.txt b/CMakeLists.txt index 6918ae0..2a5733c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -152,6 +152,10 @@ if (DOXYGEN_FOUND) set(MODELS_OUT ${CMAKE_CURRENT_BINARY_DIR}/doc/modelspage.md) configure_file(${MODELS_IN} ${MODELS_OUT} @ONLY) + set(README_IN ${CMAKE_CURRENT_SOURCE_DIR}/doc/readme.md.in) + set(README_OUT ${CMAKE_CURRENT_BINARY_DIR}/doc/readme.md) + configure_file(${README_IN} ${README_OUT} @ONLY) + message("Doxygen build started") add_custom_target(doc diff --git a/README.md b/README.md index 15b89a0..b91313a 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,3 @@ -[comment]: \page README Readme - # eisgenerator eisgenerator is a shared library (libeisgenerator.so) and CLI application that allows one to generate [EIS](https://de.wikipedia.org/wiki/Impedanzspektroskopie) spectra with high performance. diff --git a/doc/CompiledExecution.pdf b/doc/CompiledExecution.pdf new file mode 100644 index 0000000000000000000000000000000000000000..46e54fdf097ec008b36106fda3a69fe0d495bdbb GIT binary patch literal 12322 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 S8keDwftd-Hs;aBM8y5h8mmxg> literal 0 HcmV?d00001 diff --git a/doc/DirectExecution.pdf b/doc/DirectExecution.pdf new file mode 100644 index 0000000000000000000000000000000000000000..90cbcf04126a6e912de468b74f68a36a9e808465 GIT binary patch literal 12401 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 Oniz4Zs=E5SaRC5sZaUBa literal 0 HcmV?d00001 diff --git a/doc/TorchExecution.pdf b/doc/TorchExecution.pdf new file mode 100644 index 0000000000000000000000000000000000000000..2363cdd4d58f4e80cc4619e17fb73c3c2f5340db GIT binary patch literal 12828 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 literal 0 HcmV?d00001 diff --git a/doc/_r-c_r.pdf b/doc/_r-c_r.pdf new file mode 100644 index 0000000000000000000000000000000000000000..39a2f6618285c735fef9a4bc1e02265ec9eb2494 GIT binary patch literal 2170 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 literal 0 HcmV?d00001 diff --git a/doc/libeisgenerator.doxygen.in b/doc/libeisgenerator.doxygen.in index a2e801a..a10f844 100644 --- a/doc/libeisgenerator.doxygen.in +++ b/doc/libeisgenerator.doxygen.in @@ -259,7 +259,7 @@ ALIASES = # members will be omitted, etc. # The default value is: NO. -OPTIMIZE_OUTPUT_FOR_C = YES +OPTIMIZE_OUTPUT_FOR_C = NO # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or # Python sources only. Doxygen will then generate output that is more tailored @@ -864,7 +864,7 @@ WARN_LOGFILE = # spaces. See also FILE_PATTERNS and EXTENSION_MAPPING # Note: If this tag is empty the current directory is searched. -INPUT = @CMAKE_CURRENT_SOURCE_DIR@/eisgenerator @CMAKE_CURRENT_BINARY_DIR@/doc/mainpage.md @CMAKE_CURRENT_BINARY_DIR@/doc/modelspage.md @CMAKE_CURRENT_SOURCE_DIR@/README.md +INPUT = @CMAKE_CURRENT_SOURCE_DIR@/eisgenerator @CMAKE_CURRENT_BINARY_DIR@/doc/mainpage.md @CMAKE_CURRENT_BINARY_DIR@/doc/modelspage.md @CMAKE_CURRENT_SOURCE_DIR@/README.md @CMAKE_CURRENT_BINARY_DIR@/doc/readme.md # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses diff --git a/doc/mainpage.md.in b/doc/mainpage.md.in index 1f306cd..8e3d70a 100644 --- a/doc/mainpage.md.in +++ b/doc/mainpage.md.in @@ -25,6 +25,7 @@ lib@PROJECT_NAME@ incorporates three execution models to choose from depending o Upon invocation of eis::Model::Model the model string is parsed into a tree of objects. In the default tree execution the model parameters and frequencies are passed down the tree with the help of the virtual function tables of the the objects in question (black arrows). The results are then passed up the tree (blue arrows), see figure below: \image html DirectExecution.svg width=80% +\image latex DirectExecution.pdf width=\textwidth/2 This execution model has the advantage of very low latency at the expense of throughput. It is most optimal if few impedances are to be calculated. This execution model will be chosen by default. @@ -32,20 +33,22 @@ This execution model is always chosen by the single data point eis::Model::execu ### Compiled execution -In compiled execution eis::Model::compile generates a c++ function containing an implementation of of the equivalent circuit. This code is then compiled by GCC and loaded and cached by lib@PROJECT_NAME@. Subsequent calls to eis::Model::compile will then use the cached object. -Once a model has been compiled any subsequent use of the execute family of methods will us the compiled object instead of tree execution. +In compiled execution eis::Model::compile generates a c++ function containing an implementation of the equivalent circuit. This code is then compiled by GCC and loaded and cached by lib@PROJECT_NAME@. Subsequent calls to eis::Model::compile will then use the cached object. +Once a model has been compiled any, subsequent use of the execute family of methods will use the compiled object instead of tree execution. This results in a speedup of greater than 10x from the reduction in virtual function call overhead and the usage of auto-vectorization. \image html CompiledExecution.svg width=80% +\image latex CompiledExecution.pdf width=\textwidth/2 This execution model is the most performant option when evaluation of many impedances is desired and execution is to be performed on a CPU. This execution model is only available on UNIX and UNIX-like platforms providing [dlopen()](https://man7.org/linux/man-pages/man3/dlopen.3.html) and [fork()](https://www.man7.org/linux/man-pages/man2/fork.2.html). ### TorchScript execution -The final execution model generates a [TorchScript](https://pytorch.org/docs/stable/jit.html) for the equivalent circuit which can be compiled using [torch::jit::compile](https://pytorch.org/cppdocs/api/function_namespacetorch_1_1jit_1a8660dc13a6b82336aadac667e6dccba1.html) into a graph of torch/rocBLAS/cuBLAS GPU kernels for GPU execution. This provides the highest possible performance. Due to the high latency associated with executing GPU kernels this methods should only be expected to outperform compiled execution if 10^8 or more data points are required and only performs well when a large batch of data points is required at a time. This version is also highly advantageous when calculating impedance spectra as part of a larger system requiring GPU execution as in this case expensive device->host->device copies are avoided. Though torch autograd this version also provides atomatic derivatives making it useful where integration into machine-learning backward passes is required. Due to deficiencies in the windows port of Torch this version massively underperforms on Microsoft Windows and another platform should be used. +The final execution model generates a [TorchScript](https://pytorch.org/docs/stable/jit.html) for the equivalent circuit which can be compiled using [torch::jit::compile](https://pytorch.org/cppdocs/api/function_namespacetorch_1_1jit_1a8660dc13a6b82336aadac667e6dccba1.html) into a graph of torch/rocBLAS/cuBLAS GPU kernels for GPU execution. This provides the highest possible performance. Due to the high latency associated with executing GPU kernels this method should only be expected to outperform compiled execution if a total of 10^8 or more data points are required and only performs well when a large batch of these data points is required at a time. This version is also highly advantageous when calculating impedance spectra as part of a larger system requiring GPU execution as in this case expensive device->host->device copies are avoided. Though torch autograd this version also provides atomatic derivatives making it useful where integration into machine-learning backward passes is required. Due to deficiencies in the windows port of Torch this version massively underperforms on Microsoft Windows and another platform should be used. Due to MiOpen not being available on Microsoft Windows this method is unable to perform GPU execution on this platform on AMD hardware, the CPU fallback used in this case is slower than tree execution. \image html TorchExecution.svg width=80% +\image latex TorchExecution.pdf width=\textwidth/2 ----------------------------------------------------------- diff --git a/doc/modelspage.md.in b/doc/modelspage.md.in index 23b4c7c..5e2dc20 100644 --- a/doc/modelspage.md.in +++ b/doc/modelspage.md.in @@ -1,6 +1,6 @@ \page modelpage Model Format -The model format of @PROJECT_NAME@ encodes any series/ parallel combination of implemented impedances +The model format of @PROJECT_NAME@ encodes any series/ parallel combination of implemented impedances. Currently @PROJECT_NAME@ supports the following elements which each have a number of parameters: * c: cap @@ -9,13 +9,15 @@ Currently @PROJECT_NAME@ supports the following elements which each have a numbe * one parameter: resistance {R} * l: inductor * one parameter: inductance {L} -* w: warburg element (infinite), one parameters {A} +* w: warburg element (infinite) * one parameter: Warburg coefficient {A} * p: constant phase element * two parameters: {Q, alpha} * t: finite approximation of a transition line * three parameters: capacitance, resistance, approximation order {C, R, n} +Element identifiers are case insensitive. + ## Combinations Combinations of these elements are achieved by writing them against each other for a parallel combination, or with a '-' in between for serial combinations: @@ -23,28 +25,32 @@ Combinations of these elements are achieved by writing them against each other f "r-c" is thus a serial combination of a resistor and a capacitance: | r-c | | :---- | -| \image html r-c.svg width=300px | +| \image html r-c.svg width=300px; | +| \image latex r-c.pdf width=\textwidth/2 | While "cr" is a parallel combination of a resistor and a capacitance: | rc | | :---- | -| \image html rc.svg width=300px | +| \image html rc.svg width=300px | +| \image latex rc.pdf width=\textwidth/2| While "r-cr" is a parallel combination of a resistor and a capacitance in series with another resistance, not that the implicit parallel operator has operator precedence: | r-cr | | :---- | | \image html r-rc.svg width=300px | +| \image latex r-rc.pdf width=\textwidth/2| -Brackets ( and ) are also support and modify the order of operations as one would expect "(r-c)r" is a series combination of a resistor and a capacitance in parallel with another resistance: +Brackets '(' and ')' are also supported and modify the order of operations as one would expect. Thus "(r-c)r" is a series combination of a resistor and a capacitance in parallel with another resistance: | (r-c)r | | :---- | | \image html _r-c_r.svg width=300px | +| \image latex _r-c_r.pdf width=\textwidth/2| ## Parameters -To pass circuit element parameters to @PROJECT_NAME@ a format embedded into the strings is preferred. Parameters are passed by adding them in braces behind the element thus "r{100}-c{3e-6}r{1e4}" is a 100 Ohm resistor in series with a 3 Microfarad capacitance that is in parallel with a 3 kOhm resistance. +To pass circuit element parameters to @PROJECT_NAME@ a format embedded into the strings is preferred. Parameters are passed by adding them in braces behind the element thus "r{100}-c{3e-6}r{1e4}" is a 100 Ohm resistor in series with a 3 microfarad capacitance that is in parallel with a 3 kOhm resistance. -When a element takes multiple parameters, those are separated by a ',' like so: r{5e4}-p{1e-5, 0.8} +When an element takes multiple parameters, those are separated by a ',' like so: r{5e4}p{1e-5, 0.8} Ranges are also supported, here ~ is used as a separator between the start and the end of a range, thus r{1~1e3} is a resistor with a value in a linear range between 1 and 1000 Ohms. By adding a trailing 'L' the range can be marked as distributed logarithmic in base 10, thus r{1~1e3L} is such a logarithmic range. diff --git a/doc/r-c.pdf b/doc/r-c.pdf new file mode 100644 index 0000000000000000000000000000000000000000..92f678ba4a70ed65a991faf16aeb9bb5ee1b709a GIT binary patch literal 1839 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 literal 0 HcmV?d00001 diff --git a/doc/r-rc.pdf b/doc/r-rc.pdf new file mode 100644 index 0000000000000000000000000000000000000000..c73d640fa284cdf75e42d08d6cdad358fa6e1fb3 GIT binary patch literal 2123 zcmY!laB<T$)HCH$-THRjZ!QxB1BLvgEG`=x1%02?y!4U`1ycnBg&-~k1qFS#%$$<c zA_aZ7oWzn;m(=9^lvFM|JFeoAqSVA(u8KKRBX;(Q7z&*It^J2t;=a4rCLtk40VO6A z1%afdSf;x9MK^PIrxjERByI8kJ1=(K<-1WDKfZe%?l-@bk-b)Y`s<H18a1CDdhYqR z=*ai`?UOEc*td)2Km33G@#XY|ON8S2)$ettFPs=#@A$51i`#+qr~ES1bNvpTelfY? zr<z^Y_YJc)r|z6;bW&#R4zBc+D?g9y52#+wnWYx%T5ws4ySLmZLOW-gC;Np8ZZXTm z$yZM4xVrs%p%!?U(dK#iBCkVpH=VW?RBSxqIa%Pg$V_8j6_K3_xWCyMFY0VjD)E^x zvyerRH*kvI^0_M}wN(lVCnv|L^18ds+<AlVT!Dprl#|rLxvpzj-fgj(USs_7|K`0~ zYqL66+o}~E=JsAY*YkSOnT^Msl9hJddogW?TEaHzqdSjOlpGWYT_Zew$CMUp(fxTY zEi8*V7+KDwSgS5vk;0Xrc3YFv^{8RP%$(&*6i>x$3%+EaUwqTg^RVE|lVyiq^4)Kl zHlZq`)5H7uzp0z=ou1HQcqvLpq$SF6(wc5>Z|-+;v${GnB9-G#J~*Jx==(-_;lrza zjH@?vzw)?|5mi5l@Aa!UHXDBL@;yK2V&;Yfv);5ba~J#xGqTVKtW3V{axhLTmLX$m z+OjJTzI;nh`S!ZdxH#ZZ2t&q<mDa_(TsAW&JS#c8CB#P|-Ot{xB>&txKTFv)Hv+8# zs|2p5E#mj{pE@_Cpvvh}+1WXE(?zcf9n_P^zIH<7v>vb48m6$MBJRag_c3fgcf7Ok z9fQG(r<NScJ%mga-<1<izt!q_e0T91-p?;?K9egbXuVo#?WrBl(WXCP_5GQ_Dx9+< z<%JJ5wy`H4&sAv&R#|$a;xNZ@kA!DaR=Y=Cd+%e(x@Py5iML)9?r&TvT{N@BY}&if z)eqUCu1i&`hF38BE8Kp^{=1KW%wsn}hO(6hR!qC6EHmZCrQ(I(Z=_CNsv?p(Be&t} zt>!5vE>Y{;*&gyd7BNrLSZUpOmi>?;=dX#r)?Q44ci6Vgn%O*Q!ku$wPELWJ(w?(8 zF-@F!>PGM8^m7wFII1p5l$meWVshueb4|t4^3A3m7Rqb(96S8f(BCj?hWNo0jzl5T zoDWSq1Ve?o7Tuku4N7)X&z!Sya+-KPQ-79+#;NMh9GTzbrt?2sbK}|Gh<A@>dvQse zw)-M=uVT)GfGNc{WIHEZ*j4+;byme!hczlyw;m|(aXn@zXf&n1vZnbr!^$sQuaE4A z{jgB;>xI?T)uk^N9p9H{`KkB8#Qx|flO682ZSUQqIQO<q$(-Bfo87-jUQ{}lx4!8_ z?N7Z|^78ZE*&DF+Pv7!zYMb|ZZ&uCM-uE0bZnypT?%GnsYp=+Vamao8&0CXSFPhFN zJ>M^Nr`)j%VYv@3mD&8doF}K%xl!C>WAx|yHf34tZ#~*IH}Hmkj{V)z>295Tv5z-k z<>#9ZAKbk+V_o(Oll%usHNo4Ox28&4={;Ze{BfRwSLe>Bceb-@Jg=+&!>Za?lFgNx zmjW$dQu9(kMH8qz0?`Tz3WkP;1|S6>t}(pi0+&^;6(#P$C5a`e3N|(%0Z{psXrKTp z*PI;{3>EZ~6BP^<?Cd~tc6Oj*3~IbN+#Ch{kjjEo1%3adtl*MdkV06IXaO%0{S*wr z5^kAA#U%<RP&WQz(m2@QLD#dcr%ViN7L2hV_oI3cWID)4AP<^>q(K}@BAjJtgyb%m zTR`qIGA7Dlp%VkM4;cs?zyDkFU8;}dlIdGywT`ljx*T)3vVCW}fHSYOujeJh{eSh= zzBT()vj55S-SvkUh5G^$lpGQ!7VuT}c}6-_?J||Rw0F%Ge+GqGLvj9m1%`(V?`5NI zZ{s^K`ROL(Z|CBomdg4}F*(PSUUN)9?Ye-}eviw2VSZ-ei)}Wqo8|XAd(O0jleVq4 z-!tjTw9P%77X8b1=DWQ7bKPj$y%P%(H$`%YSQgnmk5v2dS@@Itk(UOy@+B%3G%nsh z-S7Cz<avC1UUg5@{_U$c@tVv{o!J)`J1EXr5WP96Czd_P_Q~SirQ32B=p+li-WTuA zUZV0U<?ZYn;dj~gG(U*44av6JdNJPZ<>4|>#k2B19jk9!EwxQaKCj%V^~KQU@8kU| zvL&A^U;EDUCI5TJmlya87dE~J#SUuZf#U!aVG0Tg#s(H31t6XwB6-4+RYXu~8aP^D z^{geBhpmzYCEno7s#FC-NUVk{L>np?DHz3qbp++-mnaw-!sFgEFD+le&;ZOwuAY+< z5`O%j-`P01k<rD#aMPTWgoKm_>_R%T9g^NSh^<!Wn8BkI=5WQZi6hPJ8^Z#LYAa@D j2F6&{FCb5#`m(qrv8be?C^e1C(8AJ`OI6j?-;E0Z+YWxB literal 0 HcmV?d00001 diff --git a/doc/rc.pdf b/doc/rc.pdf new file mode 100644 index 0000000000000000000000000000000000000000..82ad38038195f5d9a3342e24cfa2f9298aa45f01 GIT binary patch literal 1994 zcmY!laB<T$)HCH$-THRjZ!QxB1BLvgEG`=x1%02?y!4U`1ycnBg&-~k1qFS#%$$<c zA_aZ7oWzn;m(=9^lvFM|JFeoAqSVA(u8KLm5xet33<ci45C6e#P-h=C%fmy2Q+1I8 zH<RKv4~-wS$CBf3Z<g*~tg+g5*Yg{nzkSVG_~8BAHvar27q3MX?vy*<eu&+l|IuG_ z)w+MSQ+nL~Sa12k@qd56ethdBuNwO~KUC(mx|RK9+4=R7^uwl*o1AZ#ob{}btQFF? zKa&2DW3^@Uv}n!AXD)WF-Vl{G*Y6Me)^e%o>6bz)tk-V56fyGv)9lnsj3(z!Fs!?+ zven3Y;xxl!o>vMQ4*Z<EVv<A3(y~l-B^8mKIb7Q`jTUvbEE3@QVrM+-pd)9S>WMQg zjT725yx22ubZD)V7T>5<@mMRJMe)>`r=<mM8-8vPy5#X%=hCH}*I!+=oS7tc%p*H6 zdSh6C(raGPw(1TowMC`v4qqLE9gi)Nmc8^L%lXBsIc+P-PPknbQj6W99B*W?F2g#t zMXowk_~*qI&!4?1&lVh6vS(xVvxKV6+84CWn!J7RrOUwRcj@=DGE-PK2yaVkyKv^E z(AjNA&b(~PTsgz#+?;oIXNu3Q^Lwcn_U6S*OWTQEvW3RWr*rGiv`qK>ROUOyZiR@s zfUwEJ!b44^8*`X;gshktsQcK}LSv(r_?x$z4ry?@-g?<o8kIJGQk%!=(!&Dh4Ezdx z-8^kMx?UR{a^yS~`0&pSmgudDlecV%K6}Q|(<3ikT5+MqL54dljT0PFmKc=@znN*Q zQWM0PDRF!{zhbY!hf*&O+dEsY{4DT)Yq0gW*W-sz&II>KJ##HkoBDWhw^W<+q?ch% zPJvr)m#L}<SgxFObEdn8hL-!QFq4S^Q@%eFyd-10PVUgnjk;BWL3>{>Y1nD9bFMva zzLKAZ#wp7;F-j_1^5QEdip7<7Om*p)a`EWvD!~p;8{unPug~Fm8!vZ1fm!;f&<(Hk z9~l0;&N~=h-m0wT*LqPw`sb;ajqOT$2iCIRIAT%GAo1nX1LZkNp67DE&#<_xcZU1S zT>0w5HuH||^^;Dyd`q>I@9^$5-)A@aTewd8v`(7ixfau%;4*i?ha#SpnvZ#v=O{I1 zdugu!`q3cRk5O7LH{;?VTZ<=wPrtr>$@XpDiYHvz{CD)eS1DeJ_E6vZ@?KoNV(jN> z*}s$I|EU$fW{hnyefR9x7qOEw>{2SWM9UV%*LD4R`tsqw?ZWRjoO6$m(n~MbI&ozq z$KqAF9ryL0ewW@OdDZ<x=9`PD9Oqs2h0W~dp1QQda7(E4jxDnN|F+C-_ey%hdg|%5 zKm7ThZ{3P&w{_<Y|D5}?RL$)Axi6;M8KqLCZM@QFF3f&mlK&v7CfMxwtxdeL(~B>E zE;JWddgRWd?`xTlzCZrhezwh(P_ERx6le}l%}W854WI%6L@OvLSXvl^<Uu@Rc*y}S zD_ko|+=ELJOHvhVY(N5_@*~ke0aUIyJ1Q6|=qD#C7%JG=f#mG$K*b2ubaS{l3i=_H z1*r=9{z+NECAlDlup-F<UL^S`7=k6-GK-2!6ilFO{Kb@Uu)%|_XI)R37}zWrV?pjm z^&iM|kdG7;6b#Kk(jbl{5zaC+LUI?(Eg*Lp858BO(20TBhYSRc-~X-oF4aeJ$<8IL zQy(>RDJ3iH+P<@0z?oOt*YlF${=a%x%cLuJ#eX_|*WU4gWRXUtn!^Vp=N6}Pn^!gc z`Fcz0#P?NZip&jvZq8%g)5yTbUh)3otx{i>Gt*AryHQ>KZp%l5i>IpCPZS)p@X<5e zmN@ab?b^Lr`eE$PYHa7;Tldk;)&17GpBzzv(J7NSEqa&j%~yH(<@%;|H&<jNY>MR2 z<La|;*W9Qx&%&<APS))=FEhVM!Kd%1W}DQWy4);Yye;eLK24S7rq6TK(!Xc~aH+ir zvs{*^G?TF_@NU)htpTAcJ-)7u^=B_pc@-*r>q=NW`<~_(*2W>(R$C3@!)6~Yo2t+| z|Hna=>y^1oCpJEx=pvi1$yEDz|B`IctIJovcYMkH-ty%Ie$F3_he45p8h79*0L7Pr zf`YMuIY<GBXNX9huv8Thl$r*P6<9TA3Fcv|<3MRQII}8M!4MLu;R?})3PuV>v0xoR z`S~RZhKBH{_smPnS1>dH^O0-E<b;GD|L1o$PHtp$F)-XzVPs%n^nsaEEO~;2b%&{- z#|Exu4&DwcH-Up^PL#=M9Q)SO$jESZKWhQV6R5r{E=epZsVGWK<1#ciGviWKb@g}S F0ssUfKr#RT literal 0 HcmV?d00001 diff --git a/doc/readme.md.in b/doc/readme.md.in new file mode 100644 index 0000000..2da6f94 --- /dev/null +++ b/doc/readme.md.in @@ -0,0 +1,3 @@ +\page README Readme + +\include{doc} @CMAKE_CURRENT_SOURCE_DIR@/README.md diff --git a/eisgenerator/basicmath.h b/eisgenerator/basicmath.h index b21aab8..8527fac 100644 --- a/eisgenerator/basicmath.h +++ b/eisgenerator/basicmath.h @@ -25,123 +25,124 @@ namespace eis { /** - Various math functions performed on eisgenerator types + * Various math functions performed on eisgenerator types * @defgroup MATH Math * @{ */ /** - * @brief Calculates the element wise absolute gradient at the given point of the data given + * @brief Calculates the element wise absolute gradient at the given point of the data given. * - * @param data the data to calculate the gradient on - * @param index the position in the data to calculate the gradient at - * @return the element wise absolute gradient abs(re(grad(a)))+abs(im(grad(a)))i + * @param data The data to calculate the gradient on. + * @param index The position in the data to calculate the gradient at. + * @return The element wise absolute gradient abs(re(grad(a)))+abs(im(grad(a)))i. */ std::complex<fvalue> absGrad(const std::vector<eis::DataPoint>& data, size_t index); /** - * @brief Calculates derivative at the given point of the data given + * @brief Calculates derivative at the given point of the data given. * - * @param data the data to calculate the gradient on - * @param index the position in the data to calculate the gradient at - * @return the derivative + * @param data The data to calculate the gradient on. + * @param index The position in the data to calculate the gradient at. + * @return The derivative. */ fvalue grad(const std::vector<fvalue>& data, const std::vector<fvalue>& omega, size_t index); /** - * @brief Calculates the gradient at the given point of the data given + * @brief Calculates the gradient at the given point of the data given. * - * @param data the data to calculate the gradient on - * @param index the position in the data to calculate the gradient at - * @return the gradient + * @param data The data to calculate the gradient on. + * @param index The position in the data to calculate the gradient at. + * @return The gradient. */ std::complex<fvalue> grad(const std::vector<eis::DataPoint>& data, size_t index); /** - * @brief Calculates the mean of the given data + * @brief Calculates the mean of the given data. * - * @param data the data to calculate the mean of - * @return the mean + * @param data The data to calculate the mean of. + * @return The mean */ fvalue mean(const std::vector<fvalue>& data); /** - * @brief Calculates the mean of the given data + * @brief Calculates the mean of the given data. * - * @param data the data to calculate the mean of - * @return the mean + * @param data The data to calculate the mean of. + * @return The mean */ std::complex<fvalue> mean(const std::vector<eis::DataPoint>& data); /** - * @brief Calculates the median of the given data + * @brief Calculates the median of the given data. * - * @param data the data to calculate the median of - * @return the median + * @param data The data to calculate the median of. + * @return The median. */ fvalue median(std::vector<fvalue> data); /** - * @brief Calculates the median of the given data + * @brief Calculates the median of the given data. * - * @param data the data to calculate the median of - * @return the median + * @param data The data to calculate the median of. + * @return The median. */ std::complex<fvalue> median(const std::vector<eis::DataPoint>& data); /** - * @brief Resamples the data to the given amount of points + * @brief Resamples the data to the given amount of points. * - * @param data data to resample - * @param outputSize size to resample to - * @return the resampled data + * @param data Data to resample. + * @param outputSize Size to resample to. + * @return The resampled data. */ std::vector<eis::DataPoint> rescale(const std::vector<eis::DataPoint>& data, size_t outputSize); /** - * @brief Calculates the Pearson correlation between the imaginary and the real part of the data + * @brief Calculates the Pearson correlation between the imaginary and the real part of the data. * - * @param data data to calculate the Pearson correlation on - * @return the Pearson correlation coefficient + * @param data Data to calculate the Pearson correlation on. + * @return the Pearson correlation coefficient. */ fvalue pearsonCorrelation(const std::vector<eis::DataPoint>& data); /** - * @brief Calculates the variance of the distance of the data from a centroid in the nyquist plane + * @brief Calculates the variance of the distance of the data from a centroid in the nyquist plane. * - * @param data the data to calculate on - * @param centroid the centroid to use, if nullptr is passed here, the mean of the data will be used as the centroid - * @return the Pearson correlation coefficient + * @param data The data to calculate on. + * @param centroid The centroid to use, if nullptr is passed here, the mean of the data will be used as the centroid. + * @return The Pearson correlation coefficient. */ fvalue nyquistAreaVariance(const std::vector<eis::DataPoint>& data, eis::DataPoint* centroid = nullptr); /** - * @brief Finds the maximum distance between subsequent points in the data in the nyquist plane + * @brief Finds the maximum distance between subsequent points in the data in the nyquist plane. * - * @param data the data to use - * @return the largest distance + * @param data The data to use. + * @return The largest distance. */ fvalue maximumNyquistJump(const std::vector<eis::DataPoint>& data); /** - * @brief Adds white noise to the data + * @brief Adds white noise to the data. * - * @param data the data to add noise to - * @param amplitude the amplitude of the noise - * @param relative if true the amplitude will be taken as relative to the magnitude of the data, otherwise it will be taken as an absolute value + * @param data The data to add noise to. + * @param amplitude The amplitude of the noise. + * @param relative If true, the amplitude will be taken as relative to the magnitude of the data, otherwise it will be taken as an absolute value. */ void noise(std::vector<eis::DataPoint>& data, double amplitude, bool relative); /** - * @brief Removes duplicate data points form the data - * duplicates are detected by checking the value of omega for sameness using fvalueEq with the default ulp + * @brief Removes duplicate data points form the data. + * + * Duplicates are detected by checking the value of omega for sameness using fvalueEq with the default ulp. * * @param data the data to remove duplicates from */ void removeDuplicates(std::vector<eis::DataPoint>& data); /** - * @brief Checks two fvalues for equality + * @brief Checks two fvalues for equality. * * Equality is considered given when the values are within ulp epsilons at the magnitude of the sum of operands. * @@ -152,15 +153,15 @@ namespace eis bool fvalueEq(fvalue a, fvalue b, unsigned int ulp = 4); /** - * @brief this function resamples, extrapolates and interpolates to fit the data given to the frequencies also given + * @brief This function resamples, extrapolates and interpolates to fit the data given to the frequencies also given. * * Data is resampled to the target size, interpolation for data points is performed using linear interpolation * extrapolation is performed using linear or base 10 logarithmic extrapolation. * - * @param omegas the frequencies to resample the data to - * @param data the data to resample - * @param linearExtrapolation true if linear extrapolation is to be performed, otherwise base 10 logarithmic extrapolation is used - * @return the resampled data + * @param omegas The frequencies to resample the data to. + * @param data The data to resample. + * @param linearExtrapolation true if linear extrapolation is to be performed, otherwise base 10 logarithmic extrapolation is used. + * @return The resampled data. */ std::vector<eis::DataPoint> fitToFrequencies(std::vector<fvalue> omegas, const std::vector<eis::DataPoint>& data, diff --git a/eisgenerator/eistype.h b/eisgenerator/eistype.h index 020eef1..63f227c 100644 --- a/eisgenerator/eistype.h +++ b/eisgenerator/eistype.h @@ -92,9 +92,9 @@ public: return *this; } /** - * @brief calculates the absolute value of the complex impedance + * @brief Calculates the absolute value of the complex impedance. * - * @return absolute value of the complex impedance + * @return The absolute value of the complex impedance. */ fvalue complexVectorLength() const { @@ -116,10 +116,11 @@ public: bool log = false; /**< True if the elements in the range are to be spaced in log10 increments*/ /** - * @brief calculates the distance between elements in the range - * will calculate the log10 of the distance if the range is logarithmic + * @brief Calculates the distance between elements in the range. * - * @return the distance between steps of this range + * Will calculate the log10 of the distance if the range is logarithmic. + * + * @return The linear or log distance between steps of this range. */ fvalue stepSize() const { @@ -129,9 +130,9 @@ public: } /** - * @brief calculates the value of the current step + * @brief Calculates the value of the current step. * - * @return the value of the current step + * @return The value of the current step. */ fvalue stepValue() const { @@ -139,9 +140,9 @@ public: } /** - * @brief calculates the mean of the start and the end values + * @brief Calculates the mean of the start and the end values. * - * @return the mean of the start and the end values + * @return The mean of the start and the end values. */ fvalue center() const { @@ -149,9 +150,9 @@ public: } /** - * @brief calculates the value at the given index + * @brief Calculates the value at the given index. * - * @return the value at the given index + * @return The value at the given index. */ fvalue at(size_t index) const { @@ -185,47 +186,48 @@ public: Range() = default; /** - * @brief prints the range to stdout via eis::Log + * @brief Prints the range to stdout via eis::Log. * - * @param level the eis::Log::Level to print at + * @param level The eis::Log::Level to print at. */ void print(int level) const; /** - * @brief gets a machine parseable string encoding this range + * @brief Gets a machine parseable string encoding this range. * - * @return the string + * @return The string. */ std::string getString() const; /** - * @brief checks if the values of this range are sane - * this checks for some common errors like having a end < being + * @brief Checks if the values of this range are sane/ + * + * This checks for some common errors like having a end < being. * - * @return true if sane, false if not + * @return true if sane, false if not. */ bool isSane() const; /** - * @brief this function constructs a vector that contains all elements of this range + * @brief This function constructs a vector that contains all elements of this range. * - * @return the vector with the elements of this range + * @return The vector with the elements of this range. */ std::vector<fvalue> getRangeVector() const; /** - * @brief this function creates a range from the parseable string + * @brief This function creates a range from the parseable string. * - * @throw std::invalid_argument when the string syntax is incorrect - * @return the range that was parsed from the string + * @throw std::invalid_argument when the string syntax is incorrect. + * @return The range that was parsed from the string. */ [[nodiscard]] static Range fromString(std::string str, size_t count); /** - * @brief this function creates a vector ranges from the parseable parameter array string + * @brief This function creates a vector ranges from the parseable parameter array string. * * @throw std::invalid_argument when the string syntax is incorrect - * @return the vector of ranges that was parsed from the string + * @return The vector of ranges that was parsed from the string. */ [[nodiscard]] static std::vector<Range> rangesFromParamString(const std::string& paramStr, size_t count); }; @@ -271,193 +273,204 @@ public: public: /** - * @brief Constructs a EisSpectra + * @brief Constructs an EisSpectra. * - * @param data vector of the data points of the spectra - * @param model model description string for this spectra - * @param header a free-form text that will be included in any save of this spectra - * @param labels an optional vector of giving the values of the inputs of the model to get this spectra - * @param labelNames an optional vector of names describing every input of the model + * @param data Vector of the data points of the spectra. + * @param model Model description string for this spectra. + * @param header A free-form text that will be included in any save of this spectra. + * @param labels An optional vector of giving the values of the inputs of the model to get this spectra. + * @param labelNames An optional vector of names describing every input of the model. */ EisSpectra(const std::vector<DataPoint>& data, const std::string& model, const std::string& header, std::vector<double> labels = std::vector<double>(), std::vector<std::string> labelNames = std::vector<std::string>()); /** - * @brief Constructs a EisSpectra - * this function differs from the above only in the datatype of the label - * - * @param data vector of the data points of the spectra - * @param model model description string for this spectra - * @param header a free-form text that will be included in any save of this spectra - * @param labels an optional vector of giving the values of the inputs of the model to get this spectra - * @param labelNames an optional vector of names describing every input of the model + * @brief Constructs an EisSpectra. + * + * This function differs from the above only in the datatype of the label. + * + * @param data Vector of the data points of the spectra. + * @param model Model description string for this spectra. + * @param header A free-form text that will be included in any save of this spectra. + * @param labels An optional vector of giving the values of the inputs of the model to get this spectra. + * @param labelNames An optional vector of names describing every input of the model. */ EisSpectra(const std::vector<DataPoint>& data, const std::string& model, const std::string& header, std::vector<float> labels, std::vector<std::string> labelNames = std::vector<std::string>()); /** - * @brief Constructs a EisSpectra - * this function differs from the above only in the datatype of the label - * - * @param data vector of the data points of the spectra - * @param model model description string for this spectra - * @param header a free-from text that will be included in any save of this spectra - * @param labels an optional vector of giving the values of the inputs of the model to get this spectra - * @param labelNames an optional vector of names describing every input of the model + * @brief Constructs an EisSpectra. + * + * This function differs from the above only in the datatype of the label. + * + * @param data Vector of the data points of the spectra. + * @param model Model description string for this spectra. + * @param header A free-from text that will be included in any save of this spectra. + * @param labels An optional vector of giving the values of the inputs of the model to get this spectra. + * @param labelNames An optional vector of names describing every input of the model. */ EisSpectra(const std::vector<DataPoint>& data, const std::string& model, const std::string& header, std::vector<size_t> labels, std::vector<std::string> labelNames = std::vector<std::string>()); /** - * @brief Constructs a EisSpectra - * this function differs from the above only in the datatype of the label - * - * @param data vector of the data points of the spectra - * @param model model description string for this spectra - * @param header a free-form text that will be included in any save of this spectra - * @param label a value corresponding to all inputs of the model - * @param maxLabel the number of inputs of the model + * @brief Constructs an EisSpectra. + * + * This function differs from the above only in the datatype of the label. + * + * @param data Vector of the data points of the spectra. + * @param model Model description string for this spectra. + * @param header A free-form text that will be included in any save of this spectra. + * @param label A value corresponding to all inputs of the model. + * @param maxLabel The number of inputs of the model. */ EisSpectra(const std::vector<DataPoint>& data, const std::string& model, const std::string& header, size_t label, size_t maxLabel, std::vector<std::string> labelNames = std::vector<std::string>()); /** - * @brief Constructs a EisSpectra by loading a EIS file from disk + * @brief Constructs a EisSpectra by loading an EIS file from disk. * * @throw eis::file_error if there is an error loading the file - * @param path the path to the file + * @param path The path to the file. */ EisSpectra(const std::filesystem::path& path){*this = loadFromDisk(path);} EisSpectra(){} /** - * @brief Constructs a EisSpectra by loading a EIS file from disk + * @brief Constructs a EisSpectra by loading a EIS file from disk. + * + * This function has the attribute [[nodiscard]] * * @throw eis::file_error if there is an error loading the file - * @param path the path to the file - * @return the EisSpectra + * @param path The path to the file. + * @return The EisSpectra parsed from the file. */ [[nodiscard]] static EisSpectra loadFromDisk(const std::filesystem::path& path); /** - * @brief Constructs a EisSpectra by loading a EIS file from a stream + * @brief Constructs a EisSpectra by loading a EIS file from a stream. + * + * This function has the attribute [[nodiscard]] * * @throw eis::file_error if there is an error loading the file - * @param stream the stream that contains the EIS file - * @return the EisSpectra + * @param stream The stream that contains the EIS file. + * @return The EisSpectra parsed from the stream. */ [[nodiscard]] static EisSpectra loadFromStream(std::istream& stream); /** - * @brief Constructs a EisSpectra by loading a EIS file from a stream + * @brief Sets all input values up to a maximum given by maxLabel to the value given by label. * - * @param stream the stream that contains the EIS file - * @return the EisSpectra + * @param label The value to apply to all inputs. + * @param maxLabel The maximum number of values to set. */ void setLabel(size_t label, size_t maxLabel); /** - * @brief Gets the input value of this model, where it is a single value + * @brief Gets the input value of this model, where it is a single value. * - * @return the input value + * @return The input value, */ size_t getLabel(); /** - * @brief Sets the input values of this model + * @brief Sets the input values of this model. * - * @param label the input values + * @param label The input values. */ void setSzLabels(std::vector<size_t> label); /** - * @brief Sets the input values of this model + * @brief Sets the input values of this model. * - * @param label the input values + * @param label The input values. */ void setLabels(const std::vector<double>& labelsIn); /** - * @brief Sets the input values of this model + * @brief Sets the input values of this model. * - * @param label the input values + * @param label The input values. */ void setLabels(const std::vector<float>& labelsIn); /** - * @brief Sets the input values of this model + * @brief Sets the input values of this model. * - * @param label the input values + * @param label The input values. */ std::vector<size_t> getSzLabels() const; /** - * @brief Returns true if there are multiple inputs, false otherwise + * @brief Returns true if there are multiple inputs, false otherwise. * - * @return true if there are multiple inputs, false otherwise + * @return true if there are multiple inputs, false otherwise. */ bool isMulticlass(); /** - * @brief Returns the inputs as a vector + * @brief Returns the inputs as a vector. * - * @return the inputs as a vector + * @return The inputs as a vector. */ std::vector<fvalue> getFvalueLabels(); /** - * @brief Saves the spectra to disk + * @brief Saves the spectra to disk. * - * @param path a path to the file on disk where the spectra shall be saved - * @return true on success, false on failure + * @param path A path to the file on disk where the spectra shall be saved. + * @return true on success, false on failure. */ bool saveToDisk(const std::filesystem::path& path) const; /** - * @brief Saves the spectra in the given stream + * @brief Saves the spectra in the given stream. * - * @param stream a std::ostream into which the spectra will be saved + * @param stream A std::ostream into which the spectra will be saved. */ void saveToStream(std::ostream& stream) const; }; /** - * @brief deprecated function use eis::EisSpectra::saveToDisk instead + * @brief Deprecated function use eis::EisSpectra::saveToDisk instead. */ [[deprecated]] bool saveToDisk(const EisSpectra& data, const std::filesystem::path& path); /** - * @brief deprecated function use eis::EisSpectra::loadFromDisk instead + * @brief Deprecated function use eis::EisSpectra::loadFromDisk instead. */ [[deprecated]] [[nodiscard]] EisSpectra loadFromDisk(const std::filesystem::path& path); /** -* @brief Returns the a vector of DataPoints as a pair of valarrays +* @brief Returns the a vector of DataPoints as a pair of valarrays. * -* @return a pair of valarrays first the real part and second the imaginary part +* @return A pair of valarrays first the real part and second the imaginary part. */ std::pair<std::valarray<fvalue>, std::valarray<fvalue>> eisToValarrays(const std::vector<eis::DataPoint>& b); /** -* @brief Returns the mean l2 element wise distance of he given spectra +* @brief Returns the mean l2 element wise distance of he given spectra. +* +* This function will be moved to the math API in the future. * -* @param a the first set of points -* @param b the second set of points, must be the same length as a -* @return the mean l2 distance +* @param a The first set of points. +* @param b The second set of points, must be the same length as a. +* @return The mean l2 distance. */ fvalue eisDistance(const std::vector<eis::DataPoint>& a, const std::vector<eis::DataPoint>& b); /** -* @brief Returns the mean distance of the points in a to the linearly interpolated nyquist curve of b +* @brief Returns the mean distance of the points in a to the linearly interpolated nyquist curve of b. +* +* This function will be moved to the math API in the future. * -* This implementation is quite slow +* This implementation is quite slow. * -* @param a the first set of points -* @param b the second set of points -* @return the mean nyquist distance +* @param a The first set of points. +* @param b The second set of points. +* @return The mean nyquist distance. */ fvalue eisNyquistDistance(const std::vector<eis::DataPoint>& a, const std::vector<eis::DataPoint>& b); diff --git a/eisgenerator/log.h b/eisgenerator/log.h index 940a601..0da4594 100644 --- a/eisgenerator/log.h +++ b/eisgenerator/log.h @@ -25,16 +25,22 @@ namespace eis { +/** +* Various math functions performed on eisgenerator types +* @defgroup LOG Log +* @{ +*/ + class Log { public: enum Level { - DEBUG, - INFO, - WARN, - ERROR + DEBUG, /**< Messages useful for debugging */ + INFO, /**< Messages of intrest to the user incl. progress */ + WARN, /**< Non fatal errors or problems affecting performance or numeric precision */ + ERROR /**< Fatal errors */ }; private: @@ -46,11 +52,23 @@ private: public: - static bool headers; - static Level level; + static bool headers; /**< If true output will be prefixed with a header detailing the origin of the message */ + static Level level; /**< Minimum Level required for output to be printed */ Log() {} - Log(Level type, bool endlineI = true); + /** + * @brief Constructor + * + * This Constructor is to be used like a global stream. Thus if logging is desired + * the user of this api shal use Log(DEBUG)<<"This is a debugging meesage"; + * Using this constructor to create a lvalue has some negative side effects such + * as: Possibly holding a global lock for the lifetime of the object and potenttaly + * unintuative newline behavior. + * + * @param type The Level to use for this message. + * @param endline If true an UNIX newline '\n' will be emmited when the oject is destroyed + */ + Log(Level type, bool endline = true); ~Log(); template<class T> Log &operator<<(const T &msg) @@ -64,4 +82,6 @@ public: } }; +/** @} */ + } diff --git a/eisgenerator/model.h b/eisgenerator/model.h index e9fde88..f4f4541 100644 --- a/eisgenerator/model.h +++ b/eisgenerator/model.h @@ -41,7 +41,7 @@ struct CompiledObject; */ /** -* @brief The main class of eisgenerator representing a equivalent circuit model +* @brief The main class of eisgenerator representing a equivalent circuit model. */ class Model { @@ -69,10 +69,10 @@ public: /** * @brief Constructor * - * @throws parse_errror - * @param str the model string to create a model object for - * @param paramSweepCount optionally the number of sweep point to use for parameter sweeps - * @param defaultToRange optionally a bool that if true, circuit elements not given in str are defaulted to a range instead of a fixed value + * @throws parse_errror If the model string or its parameters include invalid syntax. + * @param str The model string to create a model object for. + * @param paramSweepCount Optionally the number of sweep point to use for parameter sweeps. + * @param defaultToRange Optionally a bool that if true, circuit elements not given in str are defaulted to a range instead of a fixed value. */ Model(const std::string& str, size_t paramSweepCount = 100, bool defaultToRange = true); Model(const Model& in); @@ -80,121 +80,129 @@ public: ~Model(); /** - * @brief Adjusts the sweep count so that the total of spectra that need to be generated in the parameter sweep is close to the given value + * @brief Adjusts the sweep count so that the total of spectra that need to be generated in the parameter sweep is close to the given value. * - * @param totalCount the total number of spectra to target - * @return the number of spectra that will be generated by a parameter sweep after calling this function, should be close to, but may not be exactly totalCount + * @param totalCount The total number of spectra to target. + * @return The number of spectra that will be generated by a parameter sweep after calling this function, should be close to, but may not be exactly, totalCount. */ size_t setParamSweepCountClosestTotal(size_t totalCount); /** - * @brief Gets the impedance at the given frequency - * this method calls resolveSteps + * @brief Gets the impedance at the given frequency. * - * @param omega the frequency in rad/s to calculate the impedance at - * @param index an optional index to the parameter sweep step at which to calculate the impedance - * @return a DataPoint struct containing the result + * This method calls resolveSteps. + * + * @param omega The frequency in rad/s to calculate the impedance at. + * @param index An optional index to the parameter sweep step at which to calculate the impedance. + * @return A DataPoint struct containing the result. */ DataPoint execute(fvalue omaga, size_t index = 0); /** - * @brief Executes a frequency sweep along the given range - * this method calls resolveSteps + * @brief Executes a frequency sweep along the given range. + * + * This method calls resolveSteps. * - * @param omega the range along which to execute a frequency sweep - * @param index an optional index to the parameter sweep step at which to calculate the impedance - * @return a vector of DataPoint structs containing the impedance at every frequency in the sweep + * @param omega The range along which to execute a frequency sweep. + * @param index An optional index to the parameter sweep step at which to calculate the impedance. + * @return A vector of DataPoint structs containing the impedance at every frequency in the sweep. */ std::vector<DataPoint> executeSweep(const Range& omega, size_t index = 0); /** - * @brief Executes a frequency sweep with the given omega values + * @brief Executes a frequency sweep with the given omega values. * - * @param omega a vector of frequencies in rad/s to calculate the impedance at - * @param index an optional index to the parameter sweep step at which to calculate the impedance - * @return a vector of DataPoint structs containing the impedance at every frequency in the sweep + * @param omega A vector of frequencies in rad/s to calculate the impedance at. + * @param index An optional index to the parameter sweep step at which to calculate the impedance. + * @return A vector of DataPoint structs containing the impedance at every frequency in the sweep. */ std::vector<DataPoint> executeSweep(const std::vector<fvalue>& omega, size_t index = 0); /** - * @brief Executes a frequency sweep with the given omega values for each parameter combination in the applied parameter sweep - * this method calls resolveSteps + * @brief Executes a frequency sweep with the given omega values for each parameter combination in the applied parameter sweep. + * + * This method calls resolveSteps. * - * @param omega the range along which to execute a frequency sweep - * @return a vector of vectors of DataPoint structs containing the impedance at every frequency in the sweep with every parameter combination + * @param omega The range along which to execute a frequency sweep. + * @return A vector of vectors of DataPoint structs containing the impedance at every frequency in the sweep with every parameter combination. */ std::vector<std::vector<DataPoint>> executeAllSweeps(const Range& omega); /** - * @brief Returns the model string corresponding to this model object, without embedded parameters + * @brief Returns the model string corresponding to this model object, without embedded parameters. * - * @return the model string corresponding to this model object, without embedded parameters + * @return The model string corresponding to this model object, without embedded parameters. */ std::string getModelStr() const; /** * @brief Returns the model string corresponding to this model object, with embedded parameters - * this method calls resolveSteps * - * @param index the parameter sweep index for which to embed the parameters - * @return the model string corresponding to this model object, with embedded parameters + * This method calls resolveSteps. + * + * @param index The parameter sweep index for which to embed the parameters. + * @return The model string corresponding to this model object, with embedded parameters. */ std::string getModelStrWithParam(size_t index); /** - * @brief Returns the model string corresponding to this model object, with embedded parameters - * the parameter sweep index of the last call to resolveSteps or 0 is used + * @brief Returns the model string corresponding to this model object, with embedded parameters. + * + * Yhe parameter sweep index of the last call to resolveSteps or 0 is used. * * @return the model string corresponding to this model object, with embedded parameters */ std::string getModelStrWithParam() const; /** - * @brief Returns a unique id that is unique for this circuit, but not for this object specifically - - * @return the uid + * @brief Returns a unique id. + * + * This id is only unique for the given circuit description string, not for this object as sutch. + * + * @return The uid. */ size_t getUuid(); /** - * @brief Returns a vector of pointers to the circuit elements in this model - * the pointers can only be assumed to be valid until the next member call to this model object + * @brief Returns a vector of pointers to the circuit elements in this model. + * + * The pointers can only be assumed to be valid until the next non-const member call to this model object. * - * @param model for internal use only - * @return a vector of the circuit elements in the model + * @param model For internal use only. + * @return A vector of the circuit elements in the model. */ std::vector<Componant*> getFlatComponants(Componant *model = nullptr); /** - * @brief gets the values of the parameters of the circuit elements at the current parameter sweep step + * @brief Gets the values of the parameters of the circuit elements at the current parameter sweep step. * - * @return the values of the parameters of the circuit elements at the current parameter sweep step + * @return The values of the parameters of the circuit elements at the current parameter sweep step. */ std::vector<fvalue> getFlatParameters(); /** - * @brief gets the ranges of the parameters of the circuit elements + * @brief Gets the ranges of the parameters of the circuit elements. * - * @return the ranges of the parameters of the circuit elements + * @return The ranges of the parameters of the circuit elements. */ std::vector<Range> getFlatParameterRanges(); /** - * @brief gets the default ranges of the parameters of each type of circuit element used in the model + * @brief Gets the default ranges of the parameters of each type of circuit element used in the model. * - * @return the default ranges of the parameters of each type of circuit element used in the model + * @return The default ranges of the parameters of each type of circuit element used in the model. */ std::vector<Range> getDefaultParameters(); /** - * @brief gets the total number of parameters used by all the circuit elements in this model + * @brief Gets the total number of parameters used by all the circuit elements in this model. * - * @return the total number of parameters + * @return The total number of parameters. */ size_t getParameterCount(); /** - * @brief this function compiles the model into native vectorized code for faster execution + * @brief This function compiles the model into native vectorized code for faster execution. * * This function compiles a shared-object for this model that is then loaded by eisgenerator to * speed up execution of this model by a factor of 10 or more by employing vectorization and avoiding @@ -206,81 +214,82 @@ public: * This function is only implemented on UNIX, on other platforms this function will always return false. * This function also requires that GCC be available in PATH. * - * @return true if compile was successful, false otherwise + * @return true if compile was successful, false otherwise. */ bool compile(); /** - * @brief this member determines if the model is in a state ready to execute + * @brief This member determines if the model is in a state ready to execute. * - * @return true if the model is ready for the execute* family of methods + * @return True if the model is ready for the execute family of methods. */ bool isReady(); /** - * @brief this member resolves the parameters of all circuit elements at the given parameter sweep step + * @brief This member resolves the parameters of all circuit elements at the given parameter sweep step. * - * @param index the index to the sweep step to resolve to + * @param index The index to the sweep step to resolve to. */ void resolveSteps(int64_t index); /** - * @brief gets the total number of parameter sweep steps for the applied sweep + * @brief Gets the total number of parameter sweep steps for the applied sweep. * - * @return the total number of parameter sweep steps for the applied sweep + * @return The total number of parameter sweep steps for the applied sweep. */ size_t getRequiredStepsForSweeps(); /** - * @brief checks if the model is a sweep (i.e. has at least one parameter with a range) + * @brief Checks if the model is a sweep (i.e. has at least one parameter with a range). * - * @return true if the model contains a parameter sweep, false otherwise + * @return True if the model contains a parameter sweep, false otherwise. */ bool isParamSweep(); /** - * @brief compiles this model into efficient c++ code corresponding to the circuit of this model + * @brief Compiles this model into efficient c++ code corresponding to the circuit of this model. * - * @return the code or an empty string if compilation was unsuccessfully + * @return The code or an empty string if compilation was unsuccessfully. */ std::string getCode(); /** - * @brief compiles this model into TorchScript - * to be compiled by torch::jit::compile + * @brief Compiles this model into TorchScript + * + * Can be compiled to GPU kernel executeing bytecode by torch::jit::compile. * - * @return the TorchScript code or an empty string if compilation was unsuccessful + * @return Yhe TorchScript code or an empty string if compilation was unsuccessful. */ std::string getTorchScript(); /** - * @brief Gets the function name in the code for this model + * @brief Gets the function name in the code for this model. * - * @return the function name in the code for this model + * @return The function name in the code for this model. */ std::string getCompiledFunctionName(); /** - * @brief Gets the function name in the code returned by getTorchScript and getCode for this model + * @brief Gets the function name in the code returned by getTorchScript and getCode for this model. * - * @return the function name in the code for this model + * @return The function name in the code for this model. */ std::vector<size_t> getRecommendedParamIndices(eis::Range omegaRange, double distance, bool threaded = false); }; /** * @example simple.cpp - * A simple example in how to use eisgenerator + * A simple example in how to use eisgenerator. */ /** * @example compileing.cpp - * An example on how to use the eisgenerator compiled execution model + * An example on how to use the eisgenerator compiled execution model. */ /** * @example torchscript.cpp - * An example on how to use the eisgenerator torch execution model + * An example on how to use the eisgenerator torch execution model. */ /** @} */ diff --git a/eisgenerator/normalize.h b/eisgenerator/normalize.h index 497ca05..e1a5281 100644 --- a/eisgenerator/normalize.h +++ b/eisgenerator/normalize.h @@ -30,35 +30,36 @@ namespace eis { /** -Functions for normalization of spectra data +* Functions for normalization of spectra data * @defgroup NORM Normalization * @{ */ /** -* @brief Normalizes the data to [0,1] +* @brief Normalizes the data to [0,1]. * -* @param data the data to normalize +* @param data The data to normalize. */ void normalize(std::vector<eis::DataPoint>& data); /** -* @brief Reduces the data by removing "uninteresting" regions -* Uninteresting regions are determined by taking the first and second derivative and removing the areas where these change very little +* @brief Reduces the data by removing "uninteresting" regions. * -* @param data the data to reduce -* @return the reduced data +* Uninteresting regions are determined by taking the first and second derivative and removing the areas where these change very little. +* +* @param data The data to reduce. +* @return The reduced data. */ std::vector<eis::DataPoint> reduceRegion(const std::vector<eis::DataPoint>& data, fvalue gradThreshFactor = 0.01, bool useSecondDeiv = false); /** -* @brief Removes INF and NAN from the dataset by interpolating from neighboring points +* @brief Removes INF and NAN from the dataset by interpolating from neighboring points. * -* This function is not available when this library is compiled with fast math enabled +* The universe implodes when function is used while this library is compiled with -ffast-math enabled. * -* As a side effect, this function caps spikes to +-INF to +-10 maximally +* As a side effect, this function caps spikes to +-INF to +-10 maximally. * -* @param data the data to remove INF and NAN from +* @param data The data to remove INF and NAN from. */ void eraseSingularites(std::vector<eis::DataPoint>& data); diff --git a/eisgenerator/translators.h b/eisgenerator/translators.h index 464d98f..6c7d03f 100644 --- a/eisgenerator/translators.h +++ b/eisgenerator/translators.h @@ -34,10 +34,10 @@ namespace eis */ /** -* @brief Translates a model string for RHD instruments RelaxIS to the format used by eisgenerator +* @brief Translates a model string for RHD instruments RelaxIS to the format used by eisgenerator, * -* @throws parse_errror -* @param in the RelaxIS model string +* @throws parse_errror if the given string contains syntax errors +* @param in The RelaxIS model string. * @param params an optional vector of the parameters of the circuit elements * @return the eisgenerator model string */ @@ -49,58 +49,58 @@ std::string relaxisToEis(const std::string& in, const std::vector<double>& param * Note that any parameters embedded into the eisgenerator model string will be striped and * not included in the RelaxIS model. * -* @throws parse_errror -* @param in the eisgenerator model string -* @return the RelaxIS model string +* @throws parse_errror if the given string contains syntax errors +* @param in The eisgenerator model string. +* @return The RelaxIS model string. */ std::string eisToRelaxis(const std::string& in); /** * @brief Translates a Boukamp Circuit Description Code (CDC) string into the format used by this library * -* @throws parse_errror -* @param in the CDC string -* @return the eisgenerator model string +* @throws parse_errror if the given string contains syntax errors +* @param in The CDC string. +* @return The eisgenerator model string. */ std::string cdcToEis(std::string in); /** -* @brief Translates a string for this library a Boukamp Circuit Description Code (CDC) +* @brief Translates a string for this library a Boukamp Circuit Description Code (CDC). * * Note that any parameters embedded into the eisgenerator model string will be striped and * not included in the CDC. * -* @throws parse_errror -* @param in the eisgenerator model string -* @return the CDC string +* @throws parse_errror if the given string contains syntax errors +* @param in The eisgenerator model string. +* @return The CDC string. */ std::string eisToCdc(const std::string& in); /** -* @brief Translates a model description string as used by the MADAP library into the format used by this library +* @brief Translates a model description string as used by the MADAP library into the format used by this library. -* @param in a model description string as used by the MADAP library -* @param parameters optionally a string containing the parameters of the model in MADAP parameter format -* @return the eisgenerator model string optionally including embedded parameters +* @param in A model description string as used by the MADAP library. +* @param parameters Optionally a string containing the parameters of the model in MADAP parameter format. +* @return The eisgenerator model string optionally including embedded parameters. */ std::string madapToEis(const std::string& in, const std::string& parameters = ""); /** -* @brief Translates a string for this library a into the format used by the MADAP library +* @brief Translates a string for this library a into the format used by the MADAP library. * * Note that any parameters embedded into the eisgenerator model string will be striped and * not included in the MADAP string. * -* @throws parse_errror -* @param in the eisgenerator model string -* @return the MADAP string +* @throws parse_errror If the given string contains syntax errors. +* @param in The eisgenerator model string. +* @return The MADAP string. */ std::string eisToMadap(std::string in); /** -* @brief Given a eisgenerator model description string, this function will purge all the embedded parameters +* @brief Given a eisgenerator model description string, this function will purge all the embedded parameters. * -* @param in an eisgenerator model string +* @param in An eisgenerator model string. */ void purgeEisParamBrackets(std::string& in); -- GitLab