void Sylvester ( Int m, ElementalMatrix<F>& WPre, ElementalMatrix<F>& X, SignCtrl<Base<F>> ctrl ) { EL_DEBUG_CSE DistMatrixReadProxy<F,F,MC,MR> WProx( WPre ); auto& W = WProx.Get(); const Grid& g = W.Grid(); Sign( W, ctrl ); DistMatrix<F> WTL(g), WTR(g), WBL(g), WBR(g); PartitionDownDiagonal ( W, WTL, WTR, WBL, WBR, m ); // WTL and WBR should be the positive and negative identity, WBL should be // zero, and WTR should be -2 X Copy( WTR, X ); X *= -F(1)/F(2); // TODO: Think of how to probe for checks on other quadrants. // Add UpdateDiagonal routine to avoid explicit identity Axpy? /* typedef Base<F> Real; UpdateDiagonal( WTL, F(-1) ); const Real errorWTL = FrobeniusNorm( WTL ); const Int n = W.Height() - m; UpdateDiagonal( WBR, F(1) ); const Real errorWBR = FrobeniusNorm( WBR ); const Real errorWBL = FrobeniusNorm( WBL ); */ }
void Riccati ( ElementalMatrix<F>& WPre, ElementalMatrix<F>& X, SignCtrl<Base<F>> ctrl ) { DEBUG_CSE DistMatrixReadProxy<F,F,MC,MR> WProx( WPre ); auto& W = WProx.Get(); const Grid& g = W.Grid(); Sign( W, ctrl ); const Int n = W.Height()/2; DistMatrix<F> WTL(g), WTR(g), WBL(g), WBR(g); PartitionDownDiagonal ( W, WTL, WTR, WBL, WBR, n ); // (ML, MR) = sgn(W) - I ShiftDiagonal( W, F(-1) ); // Solve for X in ML X = -MR DistMatrix<F> ML(g), MR(g); PartitionRight( W, ML, MR, n ); MR *= -1; ls::Overwrite( NORMAL, ML, MR, X ); }
inline int Lyapunov( const DistMatrix<F>& A, const DistMatrix<F>& C, DistMatrix<F>& X ) { #ifndef RELEASE CallStackEntry cse("Sylvester"); if( A.Height() != A.Width() ) LogicError("A must be square"); if( C.Height() != A.Height() || C.Width() != A.Height() ) LogicError("C must conform with A"); if( A.Grid() != C.Grid() ) LogicError("A and C must have the same grid"); #endif const Grid& g = A.Grid(); const Int m = A.Height(); DistMatrix<F> W(g), WTL(g), WTR(g), WBL(g), WBR(g); Zeros( W, 2*m, 2*m ); PartitionDownDiagonal ( W, WTL, WTR, WBL, WBR, m ); WTL = A; Adjoint( A, WBR ); Scale( F(-1), WBR ); WTR = C; Scale( F(-1), WTR ); return Sylvester( m, W, X ); }
void flow_rain(t_env *env) { int add; int flowest[4]; int lower; int lowest; int x; int y; water_bck(env); x = 0; while (x < MAP_SIZE) { y = 0; while (y < MAP_SIZE) { flowest[0] = WTR(x, y); if (x > 0) flowest[0] = WTR(x - 1, y); flowest[1] = WTR(x, y); if (x < MAP_SIZE - 1) flowest[1] = WTR(x + 1, y); flowest[2] = WTR(x, y); if (y > 0) flowest[2] = WTR(x, y - 1); flowest[3] = WTR(x, y); if (y < MAP_SIZE - 1) flowest[3] = WTR(x, y + 1); if ((flowest[0] <= WTR(x, y)) && (flowest[1] <= WTR(x, y)) && (flowest[2] <= WTR(x, y)) && (flowest[3] <= WTR(x, y))) add = -1; else add = 0; lower = 0; lowest = WTR(x, y) + add; if (x > 0 && WTR(x - 1, y) < lowest && env->water_tmp[x][y] > 0 && env->water[x][y] > 0) { lower = 1; lowest = WTR(x - 1, y); } else if (x < MAP_SIZE - 1 && WTR(x + 1, y) < lowest && env->water_tmp[x][y] > 0 && env->water[x][y] > 0) { lower = 2; lowest = WTR(x + 1, y); } else if (y > 0 && WTR(x, y - 1) < lowest && env->water_tmp[x][y] > 0 && env->water[x][y] > 0) { lower = 3; lowest = WTR(x, y - 1); } else if (y < MAP_SIZE - 1 && WTR(x, y + 1) < lowest && env->water_tmp[x][y] > 0 && env->water[x][y] > 0) { lower = 4; lowest = WTR(x, y + 1); } if (lower == 1) { env->water[x - 1][y]++; env->water[x][y]--; } if (lower == 2) { env->water[x + 1][y]++; env->water[x][y]--; } if (lower == 3) { env->water[x][y - 1]++; env->water[x][y]--; } if (lower == 4) { env->water[x][y + 1]++; env->water[x][y]--; } y++; } x++; } }