| @@ -24,6 +24,7 @@ | |||||
| \RequirePackage{totcount} | \RequirePackage{totcount} | ||||
| \RequirePackage{calc} | \RequirePackage{calc} | ||||
| \RequirePackage{wasysym} | \RequirePackage{wasysym} | ||||
| \RequirePackage{environ} | |||||
| \usetikzlibrary{quotes, angles} | \usetikzlibrary{quotes, angles} | ||||
| @@ -149,3 +150,73 @@ | |||||
| % contradiction | % contradiction | ||||
| \newcommand{\contr}{\text{\Large\lightning}} | \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 | |||||
| @@ -125,8 +125,8 @@ | |||||
| \begin{aufgabe} | \begin{aufgabe} | ||||
| \begin{enumerate}[a)] | \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 | \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. | 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 | Die zugehörigen Zeilen haben damit immer $1$ $+$ Anzahl der verbundenen Kanten Einträge ungleich | ||||
| @@ -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 <iostream> | |||||
| #include <cstdlib> | |||||
| #include "hdnum.hh" | |||||
| // Funktion zum Aufstellen der Matrix | |||||
| template<class NumberType> | |||||
| void flussMatrix( hdnum::DenseMatrix<NumberType> &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<class NumberType> | |||||
| NumberType frobeniusNorm(const hdnum::DenseMatrix<NumberType> &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<class NumberType> | |||||
| NumberType maxEigenwert(const hdnum::DenseMatrix<NumberType> &A) { | |||||
| // Error checking | |||||
| int M(A.rowsize()); | |||||
| int N(A.colsize()); | |||||
| if(M!=N) | |||||
| HDNUM_ERROR("Matrix muss quadratisch sein!"); | |||||
| // start vektor | |||||
| hdnum::Vector<NumberType> r(N); | |||||
| r[0] = 1; | |||||
| // work copy | |||||
| hdnum::Vector<NumberType> r_tmp(N); | |||||
| hdnum::Vector<NumberType> 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<REAL> 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<REAL> B(size_b,size_b); | |||||
| for (std::size_t i=0; i<size_b; ++i) | |||||
| { | |||||
| for (std::size_t j=0; j<size_b; ++j) | |||||
| { | |||||
| B[i][j] = i+j; | |||||
| } | |||||
| } | |||||
| std::cout << "Zeilen-Summen-Norm: " << A.norm_infty() << std::endl; | |||||
| std::cout << "Spalten-Summen-Norm: " << A.norm_1() << std::endl; | |||||
| std::cout << "Frobenius-Norm: " << frobeniusNorm(A) << std::endl; | |||||
| std::cout << "Maximaler Eigenwert: " << maxEigenwert(A) << std::endl; | |||||
| return 0; | |||||
| } | |||||