2

In the declare function scope, I am trying to set randomized numbers to variables, as shown in the code:

\documentclass[12pt]{article}
\usepackage{pgfplots}
\usepackage{float}
\pgfplotsset{compat=1.17}
\usepackage{tikz}
\usetikzlibrary{shapes, arrows.meta, automata, positioning, matrix, calc}
\usepackage[margin=1in]{geometry} 
\usepackage{caption}
\usepackage{siunitx}
\begin{document}    
    \begin{figure}[H]
        \centering
        \captionsetup{skip = 5pt} %default is 10pt; I am doing this to make use of pages more efficient; if I didn't do this, then some figures would go onto the next page, and leave a lot of space at the end of the current page
        \pgfplotsset{grid style={dashed,gray}} %Both grids for this figure ONLY
        \definecolor{mycolor1}{rgb}{0.00000,0.44700,0.74100}%
        \definecolor{mycolor2}{rgb}{0.85000,0.32500,0.09800}%
        \definecolor{mycolor3}{rgb}{0.92900,0.69400,0.12500}%
        \begin{tikzpicture}[trim axis left, trim axis right, 
        declare function = {
            R1Nom = 20566; 
            R2Nom = R1Nom; 
            R3Nom = 8227; 
            LNom = 1;
            CNom = 0.1*10^{-6};
            \pgfmathsetseed{2}%Setting the seed                         
            \pgfmathparse{0.8 + 0.4*rnd}
            R1Rand1 = R1Nom*\pgfmathresult;
            \pgfmathparse{0.8 + 0.4*rnd}
            R2Rand1 = R2Nom*\pgfmathresult;
            \pgfmathparse{0.8 + 0.4*rnd}
            R3Rand1 = R3Nom*\pgfmathresult;
            \pgfmathparse{0.8 + 0.4*rnd}
            LRand1 = LNom*\pgfmathresult;
            \pgfmathparse{0.8 + 0.4*rnd}
            CRand1 = CNom*\pgfmathresult;
            RthRand1 = R1Rand1*R2Rand1/(R1Rand1 + R2Rand1);
            KRand1 = R3Rand1*R2Rand1/((R1Rand1 + R2Rand1)*(R3Rand1 + RthRand1));
            \pgfmathparse{0.8 + 0.4*rnd}
            R1Rand2 = R1Nom*\pgfmathresult;
            \pgfmathparse{0.8 + 0.4*rnd}
            R2Rand2 = R2Nom*\pgfmathresult;
            \pgfmathparse{0.8 + 0.4*rnd}
            R3Rand2 = R3Nom*\pgfmathresult;
            \pgfmathparse{0.8 + 0.4*rnd}
            LRand2 = LNom*\pgfmathresult;
            \pgfmathparse{0.8 + 0.4*rnd}
            CRand2 = CNom*\pgfmathresult;
            RthRand2 = R1Rand2*R2Rand2/(R1Rand2 + R2Rand2);
            KRand2 = R3Rand2*R2Rand2/((R1Rand2 + R2Rand2)*(R3Rand2 + RthRand2));
            \pgfmathparse{0.8 + 0.4*rnd}
            R1Rand3 = R1Nom*\pgfmathresult;
            \pgfmathparse{0.8 + 0.4*rnd}
            R2Rand3 = R2Nom*\pgfmathresult;
            \pgfmathparse{0.8 + 0.4*rnd}
            R3Rand3 = R3Nom*\pgfmathresult;
            \pgfmathparse{0.8 + 0.4*rnd}
            LRand3 = LNom*\pgfmathresult;
            \pgfmathparse{0.8 + 0.4*rnd}
            CRand3 = CNom*\pgfmathresult;
            RthRand3 = R1Rand3*R2Rand3/(R1Rand3 + R2Rand3);
            KRand3 = R3Rand3*R2Rand3/((R1Rand3 + R2Rand3)*(R3Rand3 + RthRand3));
        }
        ]
        \begin{semilogxaxis}[
        width=12cm,
        height=12cm,
        %scale only axis, this command allows dimension of the axes to match up with the specified dimensions i.e. width and height; if not placed there, then the bounding box (which include tick marks, labels, etc) will be set to those dimensions
        xlabel={$\omega$ ($\SI[per-mode = symbol]{}{\radian\per\second}$)},
        ylabel={Ampltitude ($\SI{}{\decibel}$)},
        grid=both,
        xmin = 10^0, xmax=10^6,
        ymin = -110, ymax=-10,
        samples=1000]
        \addplot [mycolor1, thick, domain = 1:10^6] {20*log10(KRand1/sqrt((1 - x^2*(LRand1*CRand1*R3Rand1/(R3Rand1 + RthRand1)))^2 + x^2*(LRand1 + CRand1*R3Rand1*RthRand1)^2/(R3Rand1 + RthRand1)^2))};
        \addplot [mycolor2, thick, domain = 1:10^6] {20*log10(KRand2/sqrt((1 - x^2*(LRand2*CRand2*R3Rand2/(R3Rand2 + RthRand2)))^2 + x^2*(LRand2 + CRand2*R3Rand2*RthRand2)^2/(R3Rand2 + RthRand2)^2))};
        \addplot [mycolor3, thick, domain = 1:10^6] {20*log10(KRand3/sqrt((1 - x^2*(LRand3*CRand3*R3Rand3/(R3Rand3 + RthRand3)))^2 + x^2*(LRand3 + CRand3*R3Rand3*RthRand3)^2/(R3Rand3 + RthRand3)^2))};
        \end{semilogxaxis}
        \end{tikzpicture}
        \caption{This plot.}
    \end{figure}
\end{document}

However, I am getting an error relating to pgfmath saying: Package PGF Math Error: Unknown operator =' or =@' (in '='). ]

What is the proper way of using a random number generator in declare function?

2

You cannot put \pgfmathparse into declare function. Moreover, CNom = 0.1*10^{-6}; is incorrect, but e.g. CNom = 0.1*10^(-6); works. You probably want to use one constant random per variable, so the perhaps easiest way is to store those in macros.

\documentclass[12pt]{article}
\usepackage{pgfplots}
\usepackage{float}
\pgfplotsset{compat=1.17}
\usepackage[margin=1in]{geometry} 
\usepackage{caption}
\usepackage{siunitx}
\begin{document}    
    \begin{figure}[H]
        \centering
        \captionsetup{skip = 5pt} %default is 10pt; I am doing this to make use of pages more efficient; if I didn't do this, then some figures would go onto the next page, and leave a lot of space at the end of the current page
        \pgfplotsset{grid style={dashed,gray}} %Both grids for this figure ONLY
        \definecolor{mycolor1}{rgb}{0.00000,0.44700,0.74100}%
        \definecolor{mycolor2}{rgb}{0.85000,0.32500,0.09800}%
        \definecolor{mycolor3}{rgb}{0.92900,0.69400,0.12500}%
        \begin{tikzpicture}[trim axis left, trim axis right,
            declare function={myrnd=0.8 + 0.4*rnd;}]
        \pgfmathsetseed{2}%Setting the seed                     
        \pgfmathsetmacro{\rndA}{myrnd}
        \pgfmathsetmacro{\rndB}{myrnd}
        \pgfmathsetmacro{\rndC}{myrnd}
        \pgfmathsetmacro{\rndD}{myrnd}
        \pgfmathsetmacro{\rndE}{myrnd}
        \pgfmathsetmacro{\rndF}{myrnd}
        \pgfmathsetmacro{\rndG}{myrnd}
        \pgfmathsetmacro{\rndH}{myrnd}
        \pgfmathsetmacro{\rndI}{myrnd}
        \pgfmathsetmacro{\rndJ}{myrnd}
        \pgfmathsetmacro{\rndK}{myrnd}
        \pgfmathsetmacro{\rndL}{myrnd}
        \pgfmathsetmacro{\rndM}{myrnd}
        \pgfmathsetmacro{\rndN}{myrnd}
        \begin{semilogxaxis}[ declare function = {
            R1Nom = 20566; 
            R2Nom = R1Nom; 
            R3Nom = 8227; 
            LNom = 1;
            CNom = 0.1*10^(-6);
            R1Rand1 = R1Nom*\rndA;
            R2Rand1 = R2Nom*\rndB;
            R3Rand1 = R3Nom*\rndC;
            LRand1 = LNom*\rndD;
            CRand1 = CNom*\rndE;
            RthRand1 = R1Rand1*R2Rand1/(R1Rand1 + R2Rand1);
            KRand1 = R3Rand1*R2Rand1/((R1Rand1 + R2Rand1)*(R3Rand1 + RthRand1));
            R1Rand2 = R1Nom*\rndF;
            R2Rand2 = R2Nom*\rndF;
            R3Rand2 = R3Nom*\rndG;
            LRand2 = LNom*\rndH;
            CRand2 = CNom*\rndI;
            RthRand2 = R1Rand2*R2Rand2/(R1Rand2 + R2Rand2);
            KRand2 = R3Rand2*R2Rand2/((R1Rand2 + R2Rand2)*(R3Rand2 + RthRand2));
            R1Rand3 = R1Nom*\rndJ;
            R2Rand3 = R2Nom*\rndK;
            R3Rand3 = R3Nom*\rndL;
            LRand3 = LNom*\rndM;
            CRand3 = CNom*\rndN;
            RthRand3 = R1Rand3*R2Rand3/(R1Rand3 + R2Rand3);
            KRand3 = R3Rand3*R2Rand3/((R1Rand3 + R2Rand3)*(R3Rand3 + RthRand3));
        },
        width=12cm,
        height=12cm,
        %scale only axis, this command allows dimension of the axes to match up with the specified dimensions i.e. width and height; if not placed there, then the bounding box (which include tick marks, labels, etc) will be set to those dimensions
        xlabel={$\omega$ ($\SI[per-mode = symbol]{}{\radian\per\second}$)},
        ylabel={Ampltitude ($\SI{}{\decibel}$)},
        grid=both,
        xmin = 10^0, xmax=10^6,
        ymin = -110, ymax=-10,
        samples=101]
        \addplot [mycolor1, thick, domain = 1:10^6] {20*log10(KRand1/sqrt((1 - x^2*(LRand1*CRand1*R3Rand1/(R3Rand1 + RthRand1)))^2 + x^2*(LRand1 + CRand1*R3Rand1*RthRand1)^2/(R3Rand1 + RthRand1)^2))};
        \addplot [mycolor2, thick, domain = 1:10^6] {20*log10(KRand2/sqrt((1 - x^2*(LRand2*CRand2*R3Rand2/(R3Rand2 + RthRand2)))^2 + x^2*(LRand2 + CRand2*R3Rand2*RthRand2)^2/(R3Rand2 + RthRand2)^2))};
        \addplot [mycolor3, thick, domain = 1:10^6] {20*log10(KRand3/sqrt((1 - x^2*(LRand3*CRand3*R3Rand3/(R3Rand3 + RthRand3)))^2 + x^2*(LRand3 + CRand3*R3Rand3*RthRand3)^2/(R3Rand3 + RthRand3)^2))};
        \end{semilogxaxis}
        \end{tikzpicture}
        \caption{This plot.}
    \end{figure}
\end{document}

enter image description here

You can shorten this using a \loop.

\documentclass[12pt]{article}
\usepackage{pgfplots}
\usepackage{float}
\pgfplotsset{compat=1.17}
\usepackage[margin=1in]{geometry} 
\usepackage{caption}
\usepackage{siunitx}
\newcounter{iloop}
\begin{document}    
    \begin{figure}[H]
        \centering
        \captionsetup{skip = 5pt} %default is 10pt; I am doing this to make use of pages more efficient; if I didn't do this, then some figures would go onto the next page, and leave a lot of space at the end of the current page
        \pgfplotsset{grid style={dashed,gray}} %Both grids for this figure ONLY
        \definecolor{mycolor1}{rgb}{0.00000,0.44700,0.74100}%
        \definecolor{mycolor2}{rgb}{0.85000,0.32500,0.09800}%
        \definecolor{mycolor3}{rgb}{0.92900,0.69400,0.12500}%
        \begin{tikzpicture}[trim axis left, trim axis right,
            declare function={myrnd=0.8 + 0.4*rnd;}]
        \pgfmathsetseed{2}%Setting the seed 
        \setcounter{iloop}{0}
        \loop                   
         \stepcounter{iloop}
         \pgfmathparse{myrnd}
         \expandafter\edef\csname rnd\Alph{iloop}\endcsname{\pgfmathresult}
         \ifnum\value{iloop}<14
        \repeat
        \begin{semilogxaxis}[ declare function = {
            R1Nom = 20566; 
            R2Nom = R1Nom; 
            R3Nom = 8227; 
            LNom = 1;
            CNom = 0.1*10^(-6);
            R1Rand1 = R1Nom*\rndA;
            R2Rand1 = R2Nom*\rndB;
            R3Rand1 = R3Nom*\rndC;
            LRand1 = LNom*\rndD;
            CRand1 = CNom*\rndE;
            RthRand1 = R1Rand1*R2Rand1/(R1Rand1 + R2Rand1);
            KRand1 = R3Rand1*R2Rand1/((R1Rand1 + R2Rand1)*(R3Rand1 + RthRand1));
            R1Rand2 = R1Nom*\rndF;
            R2Rand2 = R2Nom*\rndF;
            R3Rand2 = R3Nom*\rndG;
            LRand2 = LNom*\rndH;
            CRand2 = CNom*\rndI;
            RthRand2 = R1Rand2*R2Rand2/(R1Rand2 + R2Rand2);
            KRand2 = R3Rand2*R2Rand2/((R1Rand2 + R2Rand2)*(R3Rand2 + RthRand2));
            R1Rand3 = R1Nom*\rndJ;
            R2Rand3 = R2Nom*\rndK;
            R3Rand3 = R3Nom*\rndL;
            LRand3 = LNom*\rndM;
            CRand3 = CNom*\rndN;
            RthRand3 = R1Rand3*R2Rand3/(R1Rand3 + R2Rand3);
            KRand3 = R3Rand3*R2Rand3/((R1Rand3 + R2Rand3)*(R3Rand3 + RthRand3));
        },
        width=12cm,
        height=12cm,
        %scale only axis, this command allows dimension of the axes to match up with the specified dimensions i.e. width and height; if not placed there, then the bounding box (which include tick marks, labels, etc) will be set to those dimensions
        xlabel={$\omega$ ($\SI[per-mode = symbol]{}{\radian\per\second}$)},
        ylabel={Ampltitude ($\SI{}{\decibel}$)},
        grid=both,
        xmin = 10^0, xmax=10^6,
        ymin = -110, ymax=-10,
        samples=101]
        \addplot [mycolor1, thick, domain = 1:10^6] {20*log10(KRand1/sqrt((1 - x^2*(LRand1*CRand1*R3Rand1/(R3Rand1 + RthRand1)))^2 + x^2*(LRand1 + CRand1*R3Rand1*RthRand1)^2/(R3Rand1 + RthRand1)^2))};
        \addplot [mycolor2, thick, domain = 1:10^6] {20*log10(KRand2/sqrt((1 - x^2*(LRand2*CRand2*R3Rand2/(R3Rand2 + RthRand2)))^2 + x^2*(LRand2 + CRand2*R3Rand2*RthRand2)^2/(R3Rand2 + RthRand2)^2))};
        \addplot [mycolor3, thick, domain = 1:10^6] {20*log10(KRand3/sqrt((1 - x^2*(LRand3*CRand3*R3Rand3/(R3Rand3 + RthRand3)))^2 + x^2*(LRand3 + CRand3*R3Rand3*RthRand3)^2/(R3Rand3 + RthRand3)^2))};
        \end{semilogxaxis}
        \end{tikzpicture}
        \caption{This plot.}
    \end{figure}
\end{document}
9
  • Hmmm interesting, I didn’t know about not using pgfmathparse in the declare function scope, and I must have been silly in the exponent part. Thank you so much!
    – Superman
    Jun 18 '20 at 4:49
  • On a side note, as I see, calling myrnd generates a different random number each time. So far, I have used declare function for calling constants. Are there other examples of using declare function and getting different things besides rnd e.g. passing in parameters like x and returning exp(x)?
    – Superman
    Jun 18 '20 at 4:53
  • 2
    @Superman Yes, you can do declare function={f(\x)=exp(\x);} and then plot f(x) (or f(x)). The function can have up to nine variables. (More variables are possible but one has to do that differently.)
    – user194703
    Jun 18 '20 at 4:56
  • 1
    @Superman This creates macros \rndA, \rndB and so on. We need first to "bake" the macro and then to use \edef, hence \expandafter.
    – user194703
    Jun 18 '20 at 5:03
  • 2
    @Superman Yes, "bake" means create. I think this is a nice resource for that.
    – user194703
    Jun 18 '20 at 5:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.