static void calc_coefficients(AVFilterContext *ctx) { ColorMatrixContext *color = ctx->priv; double rgb_coeffd[4][3][3]; double yuv_convertd[16][3][3]; int v = 0; int i, j, k; for (i = 0; i < 4; i++) inverse3x3(rgb_coeffd[i], yuv_coeff[i]); for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { solve_coefficients(yuv_convertd[v], rgb_coeffd[i], yuv_coeff[j]); for (k = 0; k < 3; k++) { color->yuv_convert[v][k][0] = NS(yuv_convertd[v][k][0]); color->yuv_convert[v][k][1] = NS(yuv_convertd[v][k][1]); color->yuv_convert[v][k][2] = NS(yuv_convertd[v][k][2]); } if (color->yuv_convert[v][0][0] != 65536 || color->yuv_convert[v][1][0] != 0 || color->yuv_convert[v][2][0] != 0) { av_log(ctx, AV_LOG_ERROR, "error calculating conversion coefficients\n"); } v++; } } }
/* * generic matrix inverse code * * @param x, input nxn matrix * @param y, Output inverted nxn matrix * @param n, dimension of square matrix * @returns false = matrix is Singular, true = matrix inversion successful */ bool inverse(float x[], float y[], uint16_t dim) { switch(dim){ case 3: return inverse3x3(x,y); case 4: return inverse4x4(x,y); default: return inversenxn(x,y,dim); } }
Matrix4 Matrix4::InverseFast() const { // assert: only rotation and translation // First calculate the inverse of the rotation section by transposing Matrix3 inverse3x3(*this); inverse3x3.Transpose(); // Next caculate the translation inverse Vector3 translation = -GetTranslation(); translation = translation.Transform(inverse3x3); // Next generate the 4x4 inverse by combining the rotation with the translation return Matrix4(inverse3x3, translation); }
inline std::pair<typename SteadyStateUpscaler<Traits>::permtensor_t, typename SteadyStateUpscaler<Traits>::permtensor_t> SteadyStateUpscaler<Traits>:: upscaleSteadyState(const int flow_direction, const std::vector<double>& initial_saturation, const double boundary_saturation, const double pressure_drop, const permtensor_t& upscaled_perm) { static int count = 0; ++count; int num_cells = this->ginterf_.numberOfCells(); // No source or sink. std::vector<double> src(num_cells, 0.0); Opm::SparseVector<double> injection(num_cells); // Gravity. Dune::FieldVector<double, 3> gravity(0.0); if (use_gravity_) { gravity[2] = Opm::unit::gravity; } if (gravity.two_norm() > 0.0) { OPM_MESSAGE("Warning: Gravity is experimental for flow solver."); } // Set up initial saturation profile. std::vector<double> saturation = initial_saturation; // Set up boundary conditions. setupUpscalingConditions(this->ginterf_, this->bctype_, flow_direction, pressure_drop, boundary_saturation, this->twodim_hack_, this->bcond_); // Set up solvers. if (flow_direction == 0) { this->flow_solver_.init(this->ginterf_, this->res_prop_, gravity, this->bcond_); } transport_solver_.initObj(this->ginterf_, this->res_prop_, this->bcond_); // Run pressure solver. this->flow_solver_.solve(this->res_prop_, saturation, this->bcond_, src, this->residual_tolerance_, this->linsolver_verbosity_, this->linsolver_type_, false, this->linsolver_maxit_, this->linsolver_prolongate_factor_, this->linsolver_smooth_steps_); double max_mod = this->flow_solver_.postProcessFluxes(); std::cout << "Max mod = " << max_mod << std::endl; // Do a run till steady state. For now, we just do some pressure and transport steps... std::vector<double> saturation_old = saturation; for (int iter = 0; iter < simulation_steps_; ++iter) { // Run transport solver. transport_solver_.transportSolve(saturation, stepsize_, gravity, this->flow_solver_.getSolution(), injection); // Run pressure solver. this->flow_solver_.solve(this->res_prop_, saturation, this->bcond_, src, this->residual_tolerance_, this->linsolver_verbosity_, this->linsolver_type_, false, this->linsolver_maxit_, this->linsolver_prolongate_factor_, this->linsolver_smooth_steps_); max_mod = this->flow_solver_.postProcessFluxes(); std::cout << "Max mod = " << max_mod << std::endl; // Print in-out flows if requested. if (print_inoutflows_) { std::pair<double, double> w_io, o_io; computeInOutFlows(w_io, o_io, this->flow_solver_.getSolution(), saturation); std::cout << "Pressure step " << iter << "\nWater flow [in] " << w_io.first << " [out] " << w_io.second << "\nOil flow [in] " << o_io.first << " [out] " << o_io.second << std::endl; } // Output. if (output_vtk_) { writeVtkOutput(this->ginterf_, this->res_prop_, this->flow_solver_.getSolution(), saturation, std::string("output-steadystate") + '-' + boost::lexical_cast<std::string>(count) + '-' + boost::lexical_cast<std::string>(flow_direction) + '-' + boost::lexical_cast<std::string>(iter)); } // Comparing old to new. int num_cells = saturation.size(); double maxdiff = 0.0; for (int i = 0; i < num_cells; ++i) { maxdiff = std::max(maxdiff, std::fabs(saturation[i] - saturation_old[i])); } #ifdef VERBOSE std::cout << "Maximum saturation change: " << maxdiff << std::endl; #endif if (maxdiff < sat_change_threshold_) { #ifdef VERBOSE std::cout << "Maximum saturation change is under steady state threshold." << std::endl; #endif break; } // Copy to old. saturation_old = saturation; } // Compute phase mobilities. // First: compute maximal mobilities. typedef typename Super::ResProp::Mobility Mob; Mob m; double m1max = 0; double m2max = 0; for (int c = 0; c < num_cells; ++c) { this->res_prop_.phaseMobility(0, c, saturation[c], m.mob); m1max = maxMobility(m1max, m.mob); this->res_prop_.phaseMobility(1, c, saturation[c], m.mob); m2max = maxMobility(m2max, m.mob); } // Second: set thresholds. const double mob1_abs_thres = relperm_threshold_ / this->res_prop_.viscosityFirstPhase(); const double mob1_rel_thres = m1max / maximum_mobility_contrast_; const double mob1_threshold = std::max(mob1_abs_thres, mob1_rel_thres); const double mob2_abs_thres = relperm_threshold_ / this->res_prop_.viscositySecondPhase(); const double mob2_rel_thres = m2max / maximum_mobility_contrast_; const double mob2_threshold = std::max(mob2_abs_thres, mob2_rel_thres); // Third: extract and threshold. std::vector<Mob> mob1(num_cells); std::vector<Mob> mob2(num_cells); for (int c = 0; c < num_cells; ++c) { this->res_prop_.phaseMobility(0, c, saturation[c], mob1[c].mob); thresholdMobility(mob1[c].mob, mob1_threshold); this->res_prop_.phaseMobility(1, c, saturation[c], mob2[c].mob); thresholdMobility(mob2[c].mob, mob2_threshold); } // Compute upscaled relperm for each phase. ReservoirPropertyFixedMobility<Mob> fluid_first(mob1); permtensor_t eff_Kw = Super::upscaleEffectivePerm(fluid_first); ReservoirPropertyFixedMobility<Mob> fluid_second(mob2); permtensor_t eff_Ko = Super::upscaleEffectivePerm(fluid_second); // Set the steady state saturation fields for eventual outside access. last_saturation_state_.swap(saturation); // Compute the (anisotropic) upscaled mobilities. // eff_Kw := lambda_w*K // => lambda_w = eff_Kw*inv(K); permtensor_t lambda_w(matprod(eff_Kw, inverse3x3(upscaled_perm))); permtensor_t lambda_o(matprod(eff_Ko, inverse3x3(upscaled_perm))); // Compute (anisotropic) upscaled relative permeabilities. // lambda = k_r/mu permtensor_t k_rw(lambda_w); k_rw *= this->res_prop_.viscosityFirstPhase(); permtensor_t k_ro(lambda_o); k_ro *= this->res_prop_.viscositySecondPhase(); return std::make_pair(k_rw, k_ro); }
void CorotationalLinearFEM::ComputeForceAndStiffnessMatrixOfSubmesh(double * u, double * f, SparseMatrix * stiffnessMatrix, int warp, int elementLo, int elementHi) { // clear f to zero if (f != NULL) memset(f, 0, sizeof(double) * 3 * numVertices); // clear stiffness matrix to zero if (stiffnessMatrix != NULL) stiffnessMatrix->ResetToZero(); for (int el=elementLo; el < elementHi; el++) { int vtxIndex[4]; for (int vtx=0; vtx<4; vtx++) vtxIndex[vtx] = tetMesh->getVertexIndex(el, vtx); double KElement[144]; // element stiffness matrix, to be computed below; row-major if (warp > 0) { double P[16]; // the current world-coordinate positions (row-major) /* P = [ v0 v1 v2 v3 ] [ 1 1 1 1 ] */ // rows 1,2,3 for(int i=0; i<3; i++) for(int j=0; j<4; j++) P[4 * i + j] = undeformedPositions[3 * vtxIndex[j] + i] + u[3 * vtxIndex[j] + i]; // row 4 for(int j=0; j<4; j++) P[12 + j] = 1; // F = P * Inverse(M) double F[9]; // upper-left 3x3 block for(int i=0; i<3; i++) for(int j=0; j<3; j++) { F[3 * i + j] = 0; for(int k=0; k<4; k++) F[3 * i + j] += P[4 * i + k] * MInverse[el][4 * k + j]; } double R[9]; // rotation (row-major) double S[9]; // symmetric (row-major) double tolerance = 1E-6; int forceRotation = 1; PolarDecomposition::Compute(F, R, S, tolerance, forceRotation); // RK = R * K // KElement = R * K * R^T double RK[144]; // row-major WarpMatrix(KElementUndeformed[el], R, RK, KElement); // f = RK (RT x - x0) double fElement[12]; for(int i=0; i<12; i++) { fElement[i] = 0; for(int j=0; j<4; j++) for(int l=0; l<3; l++) fElement[i] += KElement[12 * i + 3 * j + l] * P[4 * l + j] - RK[12 * i + 3 * j + l] * undeformedPositions[3 * vtxIndex[j] + l]; } // add fElement into the global f if (f != NULL) { for(int j=0; j<4; j++) for(int l=0; l<3; l++) f[3 * vtxIndex[j] + l] += fElement[3 * j + l]; } // compute exact stiffness matrix if (warp == 2) { // compute G = (tr(S) I - S) R^T double G[9]; double tr = S[0] + S[4] + S[8]; double temp[9]; for(int i=0; i<9; i++) temp[i] = -S[i]; temp[0] += tr; temp[4] += tr; temp[8] += tr; // G = temp * R^T MATRIX_MULTIPLY3X3ABT(temp, R, G); double invG[9]; // invG = G^{-1} inverse3x3(G, invG); double rhs[27]; // 3 x 9 matrix (column-major) for(int i=0; i<3; i++) for(int j=0; j<3; j++) { double temp[9]; for(int k=0; k<9; k++) temp[k] = 0.0; // copy i-th row of R into column j of temp for(int k=0; k<3; k++) temp[3 * k + j] = R[3 * i + k]; // extract the skew-symmetric part SKEW_PART(temp, &rhs[3 * (3 * i + j)]); } // must undo division by 2 from inside the SKEW_PART macro for(int i=0; i<27; i++) rhs[i] *= 2.0; // solve G * omega = rhs double omega[27]; // column-major for(int i=0; i<9; i++) { MATRIX_VECTOR_MULTIPLY3X3(invG, &rhs[3 * i], &omega[3 * i]); } double dRdF[81]; // each column is skew(omega) * R ; column-major for(int i=0; i<9; i++) { double skew[9]; SKEW_MATRIX(&omega[3 * i], skew); MATRIX_MULTIPLY3X3(skew, R, &dRdF[9 * i]); } double B[3][3][9]; // re-arrange dRdF into B, for easier dRdF * dFdx multiplication (to exploit sparsity of dFdx) for(int i=0; i<3; i++) for(int j=0; j<3; j++) for(int k=0; k<3; k++) for(int l=0; l<3; l++) { int row = 3 * i + k; int column = 3 * j + l; B[i][j][3 * k + l] = dRdF[9 * column + row]; } // four pointers to a 3-vector double * minv[4] = { &MInverse[el][0], &MInverse[el][4], &MInverse[el][8], &MInverse[el][12] }; // the four rows of MInverse (last column ignored) double dRdx[108]; // derivative of the element rotation matrix with respect to the positions of the tet vertices; column-major for(int k=0; k<4; k++) for(int i=0; i<3; i++) for(int j=0; j<3; j++) { double temp[3]; MATRIX_VECTOR_MULTIPLY3X3(B[i][j], minv[k], temp); int row = 3 * i; int column = 3 * k + j; VECTOR_SET3(&dRdx[9 * column + row], temp); } // add contribution of dRdx to KElement // term 1: \hat{dR/dxl} K (R^T x - m) // compute K (R^T x - m) double tempVec[12]; // R^T x - m for(int vtx=0; vtx<4; vtx++) { double pos[3]; for(int i=0; i<3; i++) pos[i] = P[4 * i + vtx]; MATRIX_VECTOR_MULTIPLY3X3T(R, pos, &tempVec[3*vtx]); // subtract m for(int i=0; i<3; i++) tempVec[3*vtx+i] -= undeformedPositions[3 * vtxIndex[vtx] + i]; } double a[12]; // a = K * tempVec for (int i=0; i<12; i++) { a[i] = 0.0; for (int j=0; j<12; j++) a[i] += KElementUndeformed[el][12 * i + j] * tempVec[j]; } // add [\hat{dR/dxl} K R^T x]_l, l=1 to 12 for(int column=0; column<12; column++) { double b[12]; // b = \hat{dR/dxl} * a for(int j=0; j<4; j++) { MATRIX_VECTOR_MULTIPLY3X3(&dRdx[9 * column], &a[3*j], &b[3*j]); } // write b into KElement (add b to i-th column) for(int row=0; row<12; row++) KElement[12 * row + column] += b[row]; // KElement is row-major } // term 2: (R K \hat{dRdxl}^T)x // re-write positions into a for(int vtx=0; vtx<4; vtx++) { for(int i=0; i<3; i++) a[3 * vtx + i] = P[4 * i + vtx]; } // compute [\hat{dRdxl}^T x)]_l, l=1 to 12 for(int column=0; column<12; column++) { double b[12]; // b = \hat{dRdxl}^T * a for(int j=0; j<4; j++) { MATRIX_VECTOR_MULTIPLY3X3T(&dRdx[9 * column], &a[3*j], &b[3*j]); } // add RK * b to column of KElement int rowStart = 0; for (int row=0; row<12; row++) { double contrib = 0.0; for (int j=0; j<12; j++) contrib += RK[rowStart + j] * b[j]; KElement[rowStart + column] += contrib; rowStart += 12; } } } } else { // no warp memcpy(KElement, KElementUndeformed[el], sizeof(double) * 144); // f = K u double fElement[12]; for(int i=0; i<12; i++) { fElement[i] = 0; for(int j=0; j<4; j++) { fElement[i] += KElement[12 * i + 3 * j + 0] * u[3 * vtxIndex[j] + 0] + KElement[12 * i + 3 * j + 1] * u[3 * vtxIndex[j] + 1] + KElement[12 * i + 3 * j + 2] * u[3 * vtxIndex[j] + 2]; } } // add fElement into the global f if (f != NULL) { for(int j=0; j<4; j++) { f[3 * vtxIndex[j] + 0] += fElement[3 * j + 0]; f[3 * vtxIndex[j] + 1] += fElement[3 * j + 1]; f[3 * vtxIndex[j] + 2] += fElement[3 * j + 2]; } } } if (stiffnessMatrix != NULL) { int * rowIndex = rowIndices[el]; int * columnIndex = columnIndices[el]; // add KElement to the global stiffness matrix for (int i=0; i<4; i++) for (int j=0; j<4; j++) for(int k=0; k<3; k++) for(int l=0; l<3; l++) stiffnessMatrix->AddEntry(3 * rowIndex[i] + k, 3 * columnIndex[4 * i + j] + l, KElement[12 * (3 * i + k) + 3 * j + l]); } } }