Exemple #1
0
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++;
        }
    }
}
Exemple #2
0
/*
 *    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]);
    }
  }
}