diff --git a/lecture.cls b/lecture.cls index 4988e84..f74ffdc 100644 --- a/lecture.cls +++ b/lecture.cls @@ -24,6 +24,7 @@ \RequirePackage{totcount} \RequirePackage{calc} \RequirePackage{wasysym} +\RequirePackage{environ} \usetikzlibrary{quotes, angles} @@ -149,3 +150,73 @@ % contradiction \newcommand{\contr}{\text{\Large\lightning}} + +\ExplSyntaxOn + +% S-tackrelcompatible ALIGN environment +% some might also call it the S-uper ALIGN environment +% uses regular expressions to calculate the widest stackrel +% to put additional padding on both sides of relation symbols +\NewEnviron{salign} +{ + \begin{align} + \lec_insert_padding:V \BODY + \end{align} +} +% starred version that does no equation numbering +\NewEnviron{salign*} +{ + \begin{align*} + \lec_insert_padding:V \BODY + \end{align*} +} + +% some helper variables +\tl_new:N \l__lec_text_tl +\seq_new:N \l_lec_stackrels_seq +\int_new:N \l_stackrel_count_int +\int_new:N \l_idx_int +\box_new:N \l_tmp_box +\dim_new:N \l_tmp_dim_a +\dim_new:N \l_tmp_dim_b +\dim_new:N \l_tmp_dim_needed + +% function to insert padding according to widest stackrel +\cs_new_protected:Nn \lec_insert_padding:n + { + \tl_set:Nn \l__lec_text_tl { #1 } + % get all stackrels in this align environment + \regex_extract_all:nnN { \c{stackrel}{(.*?)}{(.*?)} } { #1 } \l_lec_stackrels_seq + % get number of stackrels + \int_set:Nn \l_stackrel_count_int { \seq_count:N \l_lec_stackrels_seq } + \int_set:Nn \l_idx_int { 1 } + \dim_set:Nn \l_tmp_dim_needed { 0pt } + % iterate over stackrels + \int_while_do:nn { \l_idx_int <= \l_stackrel_count_int } + { + % calculate width of text + \hbox_set:Nn \l_tmp_box {$\seq_item:Nn \l_lec_stackrels_seq { \l_idx_int + 1 }$} + \dim_set:Nn \l_tmp_dim_a {\box_wd:N \l_tmp_box} + % calculate width of relation symbol + \hbox_set:Nn \l_tmp_box {$\seq_item:Nn \l_lec_stackrels_seq { \l_idx_int + 2 }$} + \dim_set:Nn \l_tmp_dim_b {\box_wd:N \l_tmp_box} + % check if 0.5*(a-b) > minimum padding, if yes updated minimum padding + \dim_compare:nNnTF + { 1pt * \dim_ratio:nn { \l_tmp_dim_a - \l_tmp_dim_b } { 2pt } } > { \l_tmp_dim_needed } + { \dim_set:Nn \l_tmp_dim_needed { 1pt * \dim_ratio:nn { \l_tmp_dim_a - \l_tmp_dim_b } { 2pt } } } + { } + \quad + % increment list index by three, as every stackrel produces three list entries + \int_incr:N \l_idx_int + \int_incr:N \l_idx_int + \int_incr:N \l_idx_int + } + % replace all relations with align characters (&) and add the needed padding + \regex_replace_all:nnN + { (\c{approx}&|&\c{approx}|\c{equiv}&|&\c{equiv}|=&|&=|\c{le}&|&\c{le}|\c{ge}&|&\c{ge}|&\c{stackrel}{.*?}{.*?}|\c{stackrel}{.*?}{.*?}&|&\c{neq}|\c{neq}&) } + { \c{kern} \u{l_tmp_dim_needed} \1 \c{kern} \u{l_tmp_dim_needed} } + \l__lec_text_tl + \l__lec_text_tl + } +\cs_generate_variant:Nn \lec_insert_padding:n { V } +\ExplSyntaxOff diff --git a/sose2020/num/uebungen/num3.pdf b/sose2020/num/uebungen/num3.pdf index ed4fa62..ec169e3 100644 Binary files a/sose2020/num/uebungen/num3.pdf and b/sose2020/num/uebungen/num3.pdf differ diff --git a/sose2020/num/uebungen/num3.tex b/sose2020/num/uebungen/num3.tex index f54d7f3..3d2f4bb 100644 --- a/sose2020/num/uebungen/num3.tex +++ b/sose2020/num/uebungen/num3.tex @@ -125,8 +125,8 @@ \begin{aufgabe} \begin{enumerate}[a)] - \item Die Matrix ist eine $N-1\times N-1$ Matrix, da eine Gleichung für jeden Knoten - bis auf den Referenzknoten existiert. + \item Die Matrix ist eine $N^2-1 \times N^2-1$ Matrix, da eine Gleichung für jeden der $N^2$ + Knoten, bis auf den Referenzknoten existiert. \item Jeder Knoten hat entweder 2 (Ecken), 3 (Außenkanten) oder 4 (im Inneren) ein oder ausgehende Kanten. Die mit der Pumpe verbundenen Knoten, haben jeweils eine Kante mehr. Die zugehörigen Zeilen haben damit immer $1$ $+$ Anzahl der verbundenen Kanten Einträge ungleich diff --git a/sose2020/num/uebungen/rohrleitungsnetzwerk.cc b/sose2020/num/uebungen/rohrleitungsnetzwerk.cc new file mode 100644 index 0000000..ecfcd97 --- /dev/null +++ b/sose2020/num/uebungen/rohrleitungsnetzwerk.cc @@ -0,0 +1,142 @@ +// Kompilieren mit: +// +// g++ -I../hdnum/ -o rohrleitungsnetzwerk rohrleitungsnetzwerk.cc +// +// Das setzt voraus, dass ihr Programm in einem Ordner parallel zur +// entpackten HDNum Bibliothek liegt. + +#include +#include +#include "hdnum.hh" + + +// Funktion zum Aufstellen der Matrix +template +void flussMatrix( hdnum::DenseMatrix &A ) { + int M( A.rowsize() ); + int N( A.colsize() ); + if(M!=N) + HDNUM_ERROR("Matrix muss quadratisch sein!"); + + // Numerierung wie auf Zettel 3 nur mit 0 beginnend + // also v_0, ... ,v_(N^2-1) + // der Referenzknoten v_r hat Druck 0 + + // berechnung der kantenlaenge + int n = floor(sqrt(N+1)); + + for(int i = 0; i < N; i++) { + int edges = 0; + if ((i+1)%n != 0) { // nicht linker rand + edges++; + if (i-1 >= 0) A(i, i-1) = -1; // falls nicht der referenzknoten + } + if ((i+2)%n != 0) { // nicht rechter rand + edges++; + A(i, i+1) = -1; + } + if (i+n < N) { // nicht unterer rand + edges++; + A(i, i+n) = -1; + } + if (i-n >= -1) { // nicht oberer rand + edges++; + if (i-n >= 0) A(i, i-n) = -1; // falls nicht der referenzknoten + } + A(i, i) = edges; + } +} + + +// Funktion zur Berechnung der Frobenius-Norm einer Matrix +template +NumberType frobeniusNorm(const hdnum::DenseMatrix &A) { + // Error checking + int M(A.rowsize()); + int N(A.colsize()); + if(M!=N) + HDNUM_ERROR("Matrix muss quadratisch sein!"); + + NumberType result=0.0; + + // iteriere ueber alle zeilen und spalten, quadriere die elemente und summiere + for (int i=0; i < N; i++) { + for (int j=0; j < N; j++) { + result += pow(A(i,j), 2); + } + } + + // ziehe wurzel aus summe + return sqrt(result); +} + + +// Funktion zur Berechnung des betragsgrößten Eigenwertes mit Potenzmethode +template +NumberType maxEigenwert(const hdnum::DenseMatrix &A) { + // Error checking + int M(A.rowsize()); + int N(A.colsize()); + if(M!=N) + HDNUM_ERROR("Matrix muss quadratisch sein!"); + + // start vektor + hdnum::Vector r(N); + r[0] = 1; + // work copy + hdnum::Vector r_tmp(N); + hdnum::Vector diff(N); + // fuehre iterationsschritt 10000 mal aus + for (int k=0; k<10000; k++) { + A.mv(r_tmp, r); // r_tmp = Ar + r_tmp /= r_tmp.two_norm(); // normiere r_tmp + r = r_tmp; + } + A.mv(r_tmp, r); + // berechne eigenwert mit rayleigh quotient + return (r * r_tmp)/r.two_norm_2(); +} + +// Hauptprogramm +int main(int argc, char ** argv) +{ + + // Anzahl der Knoten + const int N(10); + std::cout << "Knotenanzahl N: " << N << std::endl; + + // Größe der Matrix + const int n(N*N-1); + + // Datentyp für die Matrix + typedef double REAL; + + // Matrix initialisieren + hdnum::DenseMatrix A(n,n); + + // Pretty-printing einmal setzen für alle Matrizen + A.scientific(false); + A.width(15); + + flussMatrix(A); + if (N<=4) + std::cout << A << std::endl; + + // Bei Schwierigkeiten mit Teilaufgabe a) können Sie Teilaufgaben b) + // und c) mit folgender Matrix testen + int size_b = 3; + hdnum::DenseMatrix B(size_b,size_b); + for (std::size_t i=0; i