Ejemplo n.º 1
0
    double ConvexHullProjectionConstraint::computeMargin(const Vector2& posIn2D)
    {
        bool isInside = true;

        // First check if the point is inside the convex hull or not
        iDynTree::VectorDynSize Ax(A.rows());

        toEigen(Ax) = toEigen(A)*toEigen(posIn2D);

        // If even one of the constraint is violated, then the point is outside the convex hull
        for (int i=0; i < Ax.size(); i++)
        {
            if (!(Ax(i) <= b(i)))
            {
                isInside = false;
                break;
            }
        }

        // Then, compute the distance between each segment of the convex hull and the point :
        // the minimum one is the distance of the point from the convex hull

        // We start from the last segment that do not follow the segment[i],segment[i+1] structure
        double distanceWithoutSign = distanceBetweenPointAndSegment(posIn2D,
                                                                    projectedConvexHull(projectedConvexHull.getNrOfVertices()-1),
                                                                    projectedConvexHull(0));
        // Find the minimum distance
        for (int i=0; i < projectedConvexHull.getNrOfVertices()-1; i++)
        {
            double candidateDistance = distanceBetweenPointAndSegment(posIn2D,
                                                                      projectedConvexHull(i),
                                                                      projectedConvexHull(i+1));

            if (candidateDistance < distanceWithoutSign)
            {
                distanceWithoutSign = candidateDistance;
            }
        }

        double margin;
        // If the point is inside the convex hull, we return the distance, otherwise the negated distance
        if (isInside)
        {
            margin = distanceWithoutSign;
        }
        else
        {
            margin = -distanceWithoutSign;
        }

        return margin;
    }
// Constructors
F05_schwefel_global_opt_bound::F05_schwefel_global_opt_bound (int dimension, double bias) {
	m_dimension = dimension;
	m_bias = bias;
	m_func_name = DEFAULT_FILE_DATA5;

	// Note: dimension starts from 0
	m_o = new double[m_dimension];
	m_A = new double*[m_dimension];
	for(int i=0;i<m_dimension;++i)
		m_A[i]=new double[m_dimension];

	m_B = new double[m_dimension];
	m_z = new double[m_dimension];

	double **m_data = new double*[m_dimension+1];
	for(int i=0;i<m_dimension+1;++i)
		m_data[i]=new double[m_dimension];

	// Load the shifted global optimum
	loadMatrixFromFile(DEFAULT_FILE_DATA5, m_dimension+1, m_dimension, m_data);
	for (int i = 0 ; i < m_dimension ; i ++) {
		if ((i+1) <= ceil(m_dimension / 4.0))
			m_o[i] = -100.0;
		else if ((i+1) >= floor((3.0 * m_dimension) / 4.0))
			m_o[i] = 100.0;
		else
			m_o[i] = m_data[0][i];
	}
	for (int i = 0 ; i < m_dimension ; i ++) {
		for (int j = 0 ; j < m_dimension ; j ++) {
			m_A[i][j] = m_data[i+1][j];
		}
	}
	Ax(m_B, m_A, m_o,m_dimension);
}
Ejemplo n.º 3
0
static void test_mgcr(ITER *ip, int i, MAT *Q, MAT *R)
#endif
{
    VEC vt, vt1;
    static MAT *R1 = MNULL;
    static VEC *r = VNULL, *r1 = VNULL;
    VEC *rr;
    int k, j;
    Real sm;

    /* check Q*Q^T = I */
    vt.dim = vt.max_dim = ip->b->dim;
    vt1.dim = vt1.max_dim = ip->b->dim;

    Q = m_resize(Q, i + 1, ip->b->dim);
    R1 = m_resize(R1, i + 1, i + 1);
    r = v_resize(r, ip->b->dim);
    r1 = v_resize(r1, ip->b->dim);
    MEM_STAT_REG(R1, TYPE_MAT);
    MEM_STAT_REG(r, TYPE_VEC);
    MEM_STAT_REG(r1, TYPE_VEC);

    m_zero(R1);
    for (k = 1; k <= i; k++)
        for (j = 1; j <= i; j++) {
            vt.ve = Q->me[k];
            vt1.ve = Q->me[j];
            R1->me[k][j] = in_prod(&vt, &vt1);
        }
    for (j = 1; j <= i; j++)
        R1->me[j][j] -= 1.0;
#ifndef MEX
    if (m_norm_inf(R1) > MACHEPS * ip->b->dim)
        printf(" ! (mgcr:) m_norm_inf(Q*Q^T) = %g\n", m_norm_inf(R1));
#endif

    /* check (r_i,Ap_j) = 0 for j <= i */

    ip->Ax(ip->A_par, ip->x, r);
    v_sub(ip->b, r, r);
    rr = r;
    if (ip->Bx) {
        ip->Bx(ip->B_par, r, r1);
        rr = r1;
    }

#ifndef MEX
    printf(" ||r|| = %g\n", v_norm2(rr));
#endif
    sm = 0.0;
    for (j = 1; j <= i; j++) {
        vt.ve = Q->me[j];
        sm = max(sm, in_prod(&vt,rr));
    }
#ifndef MEX
    if (sm >= MACHEPS * ip->b->dim)
        printf(" ! (mgcr:) max_j (r,Ap_j) = %g\n", sm);
#endif

}
Ejemplo n.º 4
0
static void test_gmres(ITER *ip, int i, MAT *Q, MAT *R,
                       VEC *givc, VEC *givs, double h_val)
#endif
{
    VEC vt, vt1;
    STATIC MAT *Q1=MNULL, *R1=MNULL;
    int j;

    /* test Q*A*Q^T = R  */

    Q = m_resize(Q,i+1,ip->b->dim);
    Q1 = m_resize(Q1,i+1,ip->b->dim);
    R1 = m_resize(R1,i+1,i+1);
    MEM_STAT_REG(Q1,TYPE_MAT);
    MEM_STAT_REG(R1,TYPE_MAT);

    vt.dim = vt.max_dim = ip->b->dim;
    vt1.dim = vt1.max_dim = ip->b->dim;
    for (j=0; j <= i; j++) {
        vt.ve = Q->me[j];
        vt1.ve = Q1->me[j];
        ip->Ax(ip->A_par,&vt,&vt1);
    }

    mmtr_mlt(Q,Q1,R1);
    R1 = m_resize(R1,i+2,i+1);
    for (j=0; j < i; j++)
        R1->me[i+1][j] = 0.0;
    R1->me[i+1][i] = h_val;

    for (j = 0; j <= i; j++) {
        rot_rows(R1,j,j+1,givc->ve[j],givs->ve[j],R1);
    }

    R1 = m_resize(R1,i+1,i+1);
    m_sub(R,R1,R1);
    /* if (m_norm_inf(R1) > MACHEPS*ip->b->dim)  */
#ifndef MEX
    printf(" %d. ||Q*A*Q^T - H|| = %g [cf. MACHEPS = %g]\n",
           ip->steps,m_norm_inf(R1),MACHEPS);
#endif

    /* check Q*Q^T = I */

    Q = m_resize(Q,i+1,ip->b->dim);
    mmtr_mlt(Q,Q,R1);
    for (j=0; j <= i; j++)
        R1->me[j][j] -= 1.0;
#ifndef MEX
    if (m_norm_inf(R1) > MACHEPS*ip->b->dim)
        printf(" ! m_norm_inf(Q*Q^T) = %g\n",m_norm_inf(R1));
#endif
#ifdef THREADSAFE
    M_FREE(Q1);
    M_FREE(R1);
#endif
}
void
TimeIterationPolicyLinear<mesh_Type, AssemblyPolicy, SolverPolicy>::
iterate ( vectorPtr_Type solution,
          bcContainerPtr_Type bchandler,
          const Real& currentTime )
{
    Real rhsIterNorm ( 0.0 );

    //
    // STEP 1: Updating the system
    //
    displayer().leaderPrint ( "Updating the system... " );
    *M_rhs = 0.0;
    M_systemMatrix.reset ( new matrix_Type ( *M_solutionMap ) );
    AssemblyPolicy::assembleSystem ( M_systemMatrix, M_rhs, solution, SolverPolicy::preconditioner() );
    displayer().leaderPrint ( "done\n" );

    //
    // STEP 2: Applying the boundary conditions
    //
    displayer().leaderPrint ( "Applying BC... " );
    bcManage ( *M_systemMatrix, *M_rhs, *uFESpace()->mesh(), uFESpace()->dof(), *bchandler, uFESpace()->feBd(), 1.0, currentTime );
    M_systemMatrix->globalAssemble();
    displayer().leaderPrint ( "done\n" );

    // Extra information if we want to know the exact residual
    if ( M_computeResidual )
    {
        rhsIterNorm = M_rhs->norm2();
    }

    //
    // STEP 3: Solving the system
    //
    displayer().leaderPrint ( "Solving the system... \n" );
    SolverPolicy::solve ( M_systemMatrix, M_rhs, solution );

    if ( M_computeResidual )
    {
        vector_Type Ax ( solution->map() );
        vector_Type res ( *M_rhs );
        M_systemMatrix->matrixPtr()->Apply ( solution->epetraVector(), Ax.epetraVector() );
        res.epetraVector().Update ( -1, Ax.epetraVector(), 1 );
        Real residual;
        res.norm2 ( &residual );
        residual /= rhsIterNorm;
        displayer().leaderPrint ( "Scaled residual: ", residual, "\n" );
    }
}
Ejemplo n.º 6
0
Real
SolverAztecOO::computeResidual ( vector_type& solution, vector_type& rhs )
{
    vector_type Ax ( solution.map() );
    vector_type res ( rhs );

    M_solver.GetUserMatrix()->Apply ( solution.epetraVector(), Ax.epetraVector() );

    res.epetraVector().Update ( 1, Ax.epetraVector(), -1 );

    Real residual;

    res.norm2 ( &residual );

    return residual;
}
Ejemplo n.º 7
0
// ============================================================================
double
ComputeNorm(const Epetra_RowMatrix* A, const Epetra_MultiVector* LHS,
            const Epetra_MultiVector* RHS)
{
  double TotalNorm = 0.0;

  Epetra_MultiVector Ax(*RHS);
  A->Multiply(false, *LHS, Ax);
  Ax.Update(1.0, *RHS, -1.0);

  vector<double> norm(LHS->NumVectors());
  Ax.Norm2(&norm[0]);

  for (int i = 0 ; i < LHS->NumVectors() ; ++i)
    TotalNorm += norm[i];

  return(TotalNorm);
}
// Function body
double F05_schwefel_global_opt_bound::f(double *x,int length) {
		/*double temp1 = pow((x[0]-x[2]), 2);
		double temp2 = pow((x[2]-x[3]), 2);
		double temp3 = pow((x[1]-x[4]), 2);
		double temp5 = temp1 + temp2 + temp3;
		return temp5;*/
	double max = -HUGE_VAL; //negative inf

	Ax(m_z, m_A, x,length);

	for (int i = 0 ; i < m_dimension ; i ++) {
		double temp = fabs(m_z[i] - m_B[i]);
		if (max < temp)
			max = temp;
	}

	return (max + m_bias);
}
Foam::coupledSolverPerformance Foam::coupledSmoothSolver::solve
(
    FieldField<Field, scalar>& x,
    const FieldField<Field, scalar>& b,
    const direction cmpt
) const
{
    // Prepare solver performance
    coupledSolverPerformance solverPerf(typeName, fieldName());

    // Do a minimum number of sweeps
    // HJ, 19/Jan/2009
    if (minIter() > 0)
    {
        autoPtr<coupledLduSmoother> smootherPtr = coupledLduSmoother::New
        (
            matrix_,
            bouCoeffs_,
            intCoeffs_,
            interfaces_,
            dict()
        );

        smootherPtr->smooth
        (
            x,
            b,
            cmpt,
            minIter()
        );

        solverPerf.nIterations() += minIter();
    }

    // Now do normal sweeps.  HJ, 19/Jan/2009

    FieldField<Field, scalar> Ax(x.size());
    FieldField<Field, scalar> temp(x.size());

    forAll (x, rowI)
    {
        Ax.set(rowI, new scalarField(x[rowI].size(), 0));
        temp.set(rowI, new scalarField(x[rowI].size(), 0));
    }
Ejemplo n.º 10
0
NaGePoint3D NaGePipeSurface::PointAtPara(const double uPar, const double vPar)
{
	NaGePoint3D P;
	NaGePoint3D O = baseCurve->PointAtPara(uPar);
	NaGePoint3D D;
	NaGeVector3D Dir;
	if(uPar == 1)
	{
		D = baseCurve->PointAtPara(uPar-0.001);
		Dir = NaGeVector3D(O, D);
	}
	else
	{
		D = baseCurve->PointAtPara(uPar+0.001);
		Dir = NaGeVector3D(D, O);
	}
	NaGePoint3D fp = baseCurve->PointAtPara(baseCurve->FirstParameter());
	NaGePoint3D dfp = baseCurve->PointAtPara(baseCurve->FirstParameter()+0.001);
	NaGeVector3D Z(fp, dfp);
	NaGeAxisSystem Ax(O, Z);
		
	if(circular)
	{
		NaGeCircle3d C(Ax, itsRadius);
		if(uPar == baseCurve->FirstParameter())
			C.Reverse();
		P = C.PointAtPara(vPar);
	}
	else
	{
		NaGeEllipse3d C(Ax, itsMajorRadius, itsRadius);
		if(uPar == baseCurve->FirstParameter())
			C.Reverse();
		P = C.PointAtPara(vPar);
	}

	NaGeVector3D Ref = Dir^Z;
	double ang = Dir.Angle(Z, Ref);

	P.Translate(Ax.GetPosition(), O);
	P.Rotate(NaGeOneAxis(O, Ref), -ang);

	return P;
}
Ejemplo n.º 11
0
double GradientProjection::computeCost(
        valarray<double> const &b,
        valarray<double> const &x) const {
    // computes cost = 2 b x - x A x
    double cost = 2. * dotProd(b,x);
    valarray<double> Ax(x.size());
    for (unsigned i=0; i<denseSize; i++) {
        Ax[i] = 0;
        for (unsigned j=0; j<denseSize; j++) {
            Ax[i] += (*denseQ)[i*denseSize+j]*x[j];
        }
    }
    if(sparseQ) {
        valarray<double> r(x.size());
        sparseQ->rightMultiply(x,r);
        Ax+=r;
    }
    return cost - dotProd(x,Ax);
}
Ejemplo n.º 12
0
int ML_Amesos_Solve( void *data, double x[], double rhs[] )
{
  Amesos_Handle_Type *Amesos_Handle = (Amesos_Handle_Type *) data;
  if (Amesos_Handle->A_Base == 0) return 0;

  Amesos_BaseSolver *A_Base = (Amesos_BaseSolver *) Amesos_Handle->A_Base ;

  Epetra_Time Time(A_Base->Comm());  

  Epetra_LinearProblem *Amesos_LinearProblem = (Epetra_LinearProblem *)A_Base->GetProblem() ;
  
  const Epetra_BlockMap & map = Amesos_LinearProblem->GetOperator()->OperatorDomainMap() ; 

  Epetra_Vector EV_rhs( View, map, rhs ) ;
  Epetra_Vector EV_lhs( View, map, x ) ;

  Amesos_LinearProblem->SetRHS( &EV_rhs ) ; 
  Amesos_LinearProblem->SetLHS( &EV_lhs ) ;

  A_Base->Solve() ; 

  TimeForSolve__ += Time.ElapsedTime();
  NumSolves__++;

#ifdef ML_AMESOS_DEBUG
  // verify that the residual is actually small (and print the max
  // in the destruction phase)
  Epetra_Vector Ax(map);
  
  (Amesos_LinearProblem->GetMatrix())->Multiply(false,EV_lhs,Ax);
  
  ML_CHK_ERR(Ax.Update(1.0, EV_rhs, -1.0));
  
  double residual;
  ML_CHK_ERR(Ax.Norm2(&residual));
  if( residual > MaxError__ ) MaxError__ = residual;
#endif
  
  return 0;
} //ML_Amesos_Solve()
Ejemplo n.º 13
0
Real
LinearSolver::computeResidual ( vectorPtr_Type solutionPtr )
{
    if ( !M_operator || !M_rhs )
    {
        M_displayer->leaderPrint ( "SLV-  WARNING: LinearSolver can not compute the residual if the operator and the RHS are not set!\n" );
        return -1;
    }

    vector_Type Ax ( solutionPtr->map() );
    vector_Type residual ( *M_rhs );

    M_operator->Apply ( solutionPtr->epetraVector(), Ax.epetraVector() );

    residual.epetraVector().Update ( 1, Ax.epetraVector(), -1 );

    Real residualNorm;

    residual.norm2 ( &residualNorm );

    return residualNorm;
}
Ejemplo n.º 14
0
/* Loads an binary STL file by filename
 * Returns 0 on success and -1 on failure */
int Shape::loadBinarySTL(string filename) {

    // if(getFileType(filename) != BINARY_STL) {
    //     return -1;
    // }

    triangles.clear();
    Min.x = Min.y = Min.z = numeric_limits<double>::infinity();
    Max.x = Max.y = Max.z = -numeric_limits<double>::infinity();

    ifstream file;
    file.open(filename.c_str());

    if(file.fail()) {
      cerr << _("Error: Unable to open stl file - ") << filename << endl;
      return -1;
    }

    /* Binary STL files have a meaningless 80 byte header
     * followed by the number of triangles */
    file.seekg(80, ios_base::beg);
    unsigned int num_triangles;
    unsigned char buffer[4];
    file.read(reinterpret_cast <char *> (buffer), 4);
    // Read platform independent 32-bit little-endian int.
    num_triangles = buffer[0] | buffer[1] << 8 | buffer[2] << 16 | buffer[3] << 24;
    triangles.reserve(num_triangles);

    for(uint i = 0; i < num_triangles; i++)
    {
        double a,b,c;
        a = read_double (file);
        b = read_double (file);
        c = read_double (file);
        Vector3d N(a,b,c);
        a = read_double (file);
        b = read_double (file);
        c = read_double (file);
        Vector3d Ax(a,b,c);
        a = read_double (file);
        b = read_double (file);
        c = read_double (file);
        Vector3d Bx(a,b,c);
        a = read_double (file);
        b = read_double (file);
        c = read_double (file);
        Vector3d Cx(a,b,c);

	// done in Triangle
        /* Recalculate normal vector - can't trust an STL file! */
        // Vector3d AA=Cx-Ax;
        // Vector3d BB=Cx-Bx;
	// N = AA.cross(BB).getNormalized();

        /* attribute byte count - sometimes contains face color
            information but is useless for our purposes */
        unsigned short byte_count;
        file.read(reinterpret_cast <char *> (buffer), 2);
	byte_count = buffer[0] | buffer[1] << 8;
	// Repress unused variable warning.
	(void)&byte_count;

        Triangle T(Ax,Bx,Cx);

	//cout << "bin triangle "<< N << ":\n\t" << Ax << "/\n\t"<<Bx << "/\n\t"<<Cx << endl;

        triangles.push_back(T);
    }
    file.close();
    CenterAroundXY();
    scale_factor = 1.0;
    scale_factor_x=scale_factor_y=scale_factor_z = 1.0;
    double vol = volume();
    if (vol < 0) {
      invertNormals();
      vol = -vol;
    }
    cout << _("Shape has volume ") << vol << " mm^3"<<endl;
    return 0;
}
Ejemplo n.º 15
0
VEC  *iter_cg1(ITER *ip)
#endif
{
   STATIC VEC *r = VNULL, *p = VNULL, *q = VNULL, *z = VNULL;
   Real	alpha;
   double inner,nres;
   VEC *rr;   /* rr == r or rr == z */
   
   if (ip == INULL)
     error(E_NULL,"iter_cg");
   if (!ip->Ax || !ip->b)
     error(E_NULL,"iter_cg");
   if ( ip->x == ip->b )
     error(E_INSITU,"iter_cg");
   if (!ip->stop_crit)
     error(E_NULL,"iter_cg");
   
   if ( ip->eps <= 0.0 )
     ip->eps = MACHEPS;
   
   r = v_resize(r,ip->b->dim);
   p = v_resize(p,ip->b->dim);
   q = v_resize(q,ip->b->dim);
   
   MEM_STAT_REG(r,TYPE_VEC);
   MEM_STAT_REG(p,TYPE_VEC);
   MEM_STAT_REG(q,TYPE_VEC);
   
   if (ip->Bx != (Fun_Ax)NULL) {
      z = v_resize(z,ip->b->dim);
      MEM_STAT_REG(z,TYPE_VEC);
      rr = z;
   }
   else rr = r;
   
   if (ip->x != VNULL) {
      if (ip->x->dim != ip->b->dim)
	error(E_SIZES,"iter_cg");
      ip->Ax(ip->A_par,ip->x,p);    		/* p = A*x */
      v_sub(ip->b,p,r);		 		/* r = b - A*x */
   }
   else {  /* ip->x == 0 */
      ip->x = v_get(ip->b->dim);
      ip->shared_x = FALSE;
      v_copy(ip->b,r);
   }
   
   if (ip->Bx) (ip->Bx)(ip->B_par,r,p);
   else v_copy(r,p);
   
   inner = in_prod(p,r);
   nres = sqrt(fabs(inner));
   if (ip->info) ip->info(ip,nres,r,p);
   if ( nres == 0.0) return ip->x;
   
   for ( ip->steps = 0; ip->steps <= ip->limit; ip->steps++ )
   {
      ip->Ax(ip->A_par,p,q);
      inner = in_prod(q,p);
      if (sqrt(fabs(inner)) <= MACHEPS*ip->init_res)
	error(E_BREAKDOWN,"iter_cg1");

      alpha = in_prod(p,r)/inner;
      v_mltadd(ip->x,p,alpha,ip->x);
      v_mltadd(r,q,-alpha,r);
      
      rr = r;
      if (ip->Bx) {
	 ip->Bx(ip->B_par,r,z);
	 rr = z;
      }
      
      nres = in_prod(r,rr);
      if (nres < 0.0) {
	 warning(WARN_RES_LESS_0,"iter_cg");
	 break;
      }
      nres = sqrt(fabs(nres));
      if (ip->info) ip->info(ip,nres,r,z);
      if (ip->steps == 0) ip->init_res = nres;
      if ( ip->stop_crit(ip,nres,r,z) ) break;
      
      alpha = -in_prod(rr,q)/inner;
      v_mltadd(rr,p,alpha,p);
      
   }

#ifdef	THREADSAFE
   V_FREE(r);   V_FREE(p);   V_FREE(q);   V_FREE(z);
#endif

   return ip->x;
}
Ejemplo n.º 16
0
	G(3),	0,		0,		0,		0,		0,
};

/*
 * Fuer Elise, Beethoven
 * (Excuse my non-existent musical skill, Mr. B ;-)
 */
static int tune2[96*6] = {
	D(3),	D(4),	D(5),	0,		0,		0,
	Cx(3),	Cx(4),	Cx(5),	0,		0,		0,
	D(3),	D(4),	D(5),	0,		0,		0,
	Cx(3),	Cx(4),	Cx(5),	0,		0,		0,
	D(3),	D(4),	D(5),	0,		0,		0,
	A(2),	A(3),	A(4),	0,		0,		0,
	C(3),	C(4),	C(5),	0,		0,		0,
	Ax(2),	Ax(3),	Ax(4),	0,		0,		0,
	G(2),	G(3),	G(4),	0,		0,		0,
	D(1),	D(2),	D(3),	0,		0,		0,
	G(1),	G(2),	G(3),	0,		0,		0,
	Ax(1),	Ax(2),	Ax(3),	0,		0,		0,

	D(2),	D(3),	D(4),	0,		0,		0,
	G(2),	G(3),	G(4),	0,		0,		0,
	A(2),	A(3),	A(4),	0,		0,		0,
	D(1),	D(2),	D(3),	0,		0,		0,
	A(1),	A(2),	A(3),	0,		0,		0,
	D(2),	D(3),	D(4),	0,		0,		0,
	Fx(2),	Fx(3),	Fx(4),	0,		0,		0,
	A(2),	A(3),	A(4),	0,		0,		0,
	Ax(2),	Ax(3),	Ax(4),	0,		0,		0,
	D(1),	D(2),	D(3),	0,		0,		0,
Ejemplo n.º 17
0
static real conjugate_gradient(Operator A, Operator precon, int n, real *x, real *rhs, real tol, int maxit, int *flag){
  real *z, *r, *p, *q, res = 10*tol, alpha;
  real rho = 1.0e20, rho_old = 1, res0, beta;
  real* (*Ax)(Operator o, real *in, real *out) = A->Operator_apply;
  real* (*Minvx)(Operator o, real *in, real *out) = precon->Operator_apply;
  int iter = 0;

  z = N_GNEW(n,real);
  r = N_GNEW(n,real);
  p = N_GNEW(n,real);
  q = N_GNEW(n,real);

  r = Ax(A, x, r);
  r = vector_subtract_to(n, rhs, r);

  res0 = res = sqrt(vector_product(n, r, r))/n;
#ifdef DEBUG_PRINT
    if (Verbose && 0){
      fprintf(stderr, "   cg iter = %d, residual = %g\n", iter, res);
    }
#endif

  while ((iter++) < maxit && res > tol*res0){
    z = Minvx(precon, r, z);
    rho = vector_product(n, r, z);

    if (iter > 1){
      beta = rho/rho_old;
      p = vector_saxpy(n, z, p, beta);
    } else {
      MEMCPY(p, z, sizeof(real)*n);
    }

    q = Ax(A, p, q);

    alpha = rho/vector_product(n, p, q);

    x = vector_saxpy2(n, x, p, alpha);
    r = vector_saxpy2(n, r, q, -alpha);
    
    res = sqrt(vector_product(n, r, r))/n;

#ifdef DEBUG_PRINT
    if (Verbose && 0){
      fprintf(stderr, "   cg iter = %d, residual = %g\n", iter, res);
    }
#endif



    rho_old = rho;
  }
  FREE(z); FREE(r); FREE(p); FREE(q);
#ifdef DEBUG
    _statistics[0] += iter - 1;
#endif

#ifdef DEBUG_PRINT
  if (Verbose && 0){
    fprintf(stderr, "   cg iter = %d, residual = %g\n", iter, res);
  }
#endif
  return res;
}
int main(int argc, char* argv[]) {

    int N;
    scanf("%d", &N);

    for (int s0 = 0; s0 < N; ++s0) {
        int n;
        scanf("%d", &n);
        double c;
        scanf("%lf", &c);
        int maxit;
        scanf("%d", &maxit);
        double eps;
        scanf("%lf", &eps);
        SquareMatrix A(n);
        for (int i = 1; i <= n; ++i) {
            for (int j = 1; j <= n; ++j) {
                double num;
                scanf("%lf", &num);
                A.setM(i, j, num);
            }
        }
        Vector x(n);
        for (int i = 1; i <= n; ++i) {
            double num;
            scanf("%lf", &num);
            x.setV(i, num);
        }
        SquareMatrix A1(n);
        A.copyTo(&A1);
        for (int i = 1; i <= n; ++i) {
            A1.setM(i, i, A.M(i, i) - c);
        }

        PMatrix P(n);
        A1.PLUDecomposite(&P);

        if (!A1.regular()) {
            printf("%.8lf\n", c);
            continue;
        }
        if (x.nullVector()) {
            printf("kezdovektor\n", c);
            continue;
        }

        x.multiplyScalar(1 / x.norm2());

        Vector Ax(n);
        x.leftMultiply(&A, &Ax);
        double l0 = x.scalarProduct(&Ax);
        double l1;

        int m;
        for (m = 1; m <= maxit; ++m) {
            Vector y(n);
            x.leftMultiply(&P, &y);
            A1.solve(&y);
            y.copyTo(&x);
            x.multiplyScalar(1 / x.norm2());
            x.leftMultiply(&A, &Ax);
            l1 = x.scalarProduct(&Ax);
            if (fabs(l1 - l0) < eps * (1 + fabs(l1)))	break;
            l0 = l1;
        }

        if (m > maxit) {
            printf("maxit\n");
            continue;
        }

        double d = 0;

        for (int i = 1; i <= n; ++i) {
            d += (Ax.V(i) - l1 * x.V(i)) * (Ax.V(i) - l1 * x.V(i));
        }


        printf(d <= eps ? "siker" : "sikertelen");
        printf(" %.8lf", l1);
        for (int i = 1; i <= n; ++i) {
            printf(" %.8lf", x.V(i));
        }
        printf(" %.8lf", d);
        printf("\n");
    }

    return 0;
}
void Model :: MD_3D(double le,int BstartID,int beforeN,int newN,double r,double region[3][2])
{
//分子動力学によりnewN個の粒子の位置を最適化 IDがBstartIDからBendIDまでのは境界粒子なので動かさない
	double k0=1;
	double dt=0.001;
	int BendID=beforeN;
	
	//力はax^3+bx^2+dの式を採用。文献[Bubble Mesh Automated Triangular Meshing of Non-Manifold Geometry by Sphere Packing]を参照
	double a=(r+1)/(2*r*r-r-1)*k0/(le*le);
	double b=-0.5*k0/le-1.5*a*le;
	double d=-a*le*le*le-b*le*le;
	/////////////
	int lastN=beforeN+newN;

	//cout<<"F="<<a*le*le*le+b*le*le+d<<" "<<a*1.5*le*1.5*le*1.5*le+b*1.5*le*1.5*le+d<<endl;

	vector<double> Fx(newN);	//各粒子に働くX方向力
	vector<double> Fy(newN);	//各粒子に働くY方向力
	vector<double> Fz(newN);	//各粒子に働くZ方向力
	vector<double> Ax(newN,0);	//X方向加速度
	vector<double> Ay(newN,0);	//Y方向加速度
	vector<double> Az(newN,0);	//Z方向加速度
	vector<double> U(newN,0);	//X方向速度
	vector<double> V(newN,0);	//Y方向速度
	vector<double> W(newN,0);	//Z方向速度
	vector<double> visX(newN);	//X方向粘性係数
	vector<double> visY(newN);	//Y方向粘性係数
	vector<double> visZ(newN);	//Y方向粘性係数
	vector<double> KX(newN);	//X方向バネ係数
	vector<double> KY(newN);	//Y方向バネ係数
	vector<double> KZ(newN);	//Y方向バネ係数

	//計算の高速化のために格子を形成 解析幅がr*leで割り切れるとは限らないので、はみ出したところは切り捨て。なので各軸とも正の方向には余裕を持つこと
	double grid_width=le*((int)(r+1));								//格子の幅。rを含む整数*le
	int grid_sizeX=(int)((region[A_X][1]-region[A_X][0])/grid_width);	//X方向の格子の個数
	int grid_sizeY=(int)((region[A_Y][1]-region[A_Y][0])/grid_width);
	int grid_sizeZ=(int)((region[A_Z][1]-region[A_Z][0])/grid_width);
	int grid_SIZE=grid_sizeX*grid_sizeY*grid_sizeZ;
	int plane_SIZE=grid_sizeX*grid_sizeY;
	int *index=new int[newN];									//各内部粒子を含む格子番号
	vector<int> *MESH=new vector<int>[grid_SIZE];				//各メッシュに格納される粒子ID格納

	for(int i=BstartID;i<BendID;i++)	//まずは境界粒子を格子に格納
	{
		int xn=(int)((PART[i].Get_X()-region[A_X][0])/grid_width);//X方向に何個目の格子か 
		int yn=(int)((PART[i].Get_Y()-region[A_Y][0])/grid_width);//Y方向に何個目の格子か
		int zn=(int)((PART[i].Get_Z()-region[A_Z][0])/grid_width);//Z方向に何個目の格子か
		int number=zn*grid_sizeX*grid_sizeY+yn*grid_sizeX+xn;//粒子iを含む格子の番号
		MESH[number].push_back(i);
	}
	for(int k=0;k<newN;k++)	//つぎに内部粒子を格納
	{
		int i=beforeN+k;
		int xn=(int)((PART[i].Get_X()-region[A_X][0])/grid_width);//X方向に何個目の格子か 
		int yn=(int)((PART[i].Get_Y()-region[A_Y][0])/grid_width);//Y方向に何個目の格子か
		int zn=(int)((PART[i].Get_Z()-region[A_Z][0])/grid_width);//Z方向に何個目の格子か
		int number=zn*grid_sizeX*grid_sizeY+yn*grid_sizeX+xn;//粒子iを含む格子の番号
		MESH[number].push_back(i);
		index[k]=number;
	}

	//計算開始
	for(int t=0;t<100;t++)
	{
		if(t%10==0 && t>0)
		{
			//MESHを一度破壊する。
			for(int n=0;n<grid_SIZE;n++)
			{
				size_t size=MESH[n].size();
				for(int k=0;k<size;k++) MESH[n].pop_back();
			}
			
			for(int i=BstartID;i<BendID;i++)	//まずは境界粒子を格子に格納
			{
				int xn=(int)((PART[i].Get_X()-region[A_X][0])/grid_width);//X方向に何個目の格子か 
				int yn=(int)((PART[i].Get_Y()-region[A_Y][0])/grid_width);//Y方向に何個目の格子か
				int zn=(int)((PART[i].Get_Z()-region[A_Z][0])/grid_width);//Z方向に何個目の格子か
				int number=zn*grid_sizeX*grid_sizeY+yn*grid_sizeX+xn;//粒子iを含む格子の番号
				MESH[number].push_back(i);
			}
			for(int k=0;k<newN;k++)	//つぎに内部粒子を格納
			{
				int i=beforeN+k;
				int xn=(int)((PART[i].Get_X()-region[A_X][0])/grid_width);//X方向に何個目の格子か 
				int yn=(int)((PART[i].Get_Y()-region[A_Y][0])/grid_width);//Y方向に何個目の格子か
				int zn=(int)((PART[i].Get_Z()-region[A_Z][0])/grid_width);//Z方向に何個目の格子か
				int number=zn*grid_sizeX*grid_sizeY+yn*grid_sizeX+xn;//粒子iを含む格子の番号
				MESH[number].push_back(i);
				index[k]=number;
			}
		}

		for(int k=0;k<newN;k++)
		{
			Fx[k]=0; Fy[k]=0, Fz[k]=0;			//初期化
			KX[k]=0;KY[k]=0; KZ[k]=0;			//バネ係数
		}

		for(int k=0;k<newN;k++)
		{
			int i=beforeN+k;					//対応する粒子番号
			int G_id=index[k];				//格納する格子番号
			for(int II=G_id-1;II<=G_id+1;II++)
			{       
				for(int JJ=-1*grid_sizeX;JJ<=grid_sizeX;JJ+=grid_sizeX)
				{
					for(int KK=-1*plane_SIZE;KK<=plane_SIZE;KK+=plane_SIZE)
					{
						int M_id=II+JJ+KK;
						for(int L=0;L<MESH[M_id].size();L++)
						{
							int j=MESH[M_id][L];
							if(j>=beforeN && j>i)	//同じ領域内でかつiより大きな番号なら
							{
								int J=j-beforeN;	//newN内での番号
								double x=PART[j].Get_X()-PART[i].Get_X();
								double y=PART[j].Get_Y()-PART[i].Get_Y();
								double z=PART[j].Get_Z()-PART[i].Get_Z();
								double dis=sqrt(x*x+y*y+z*z);
								if(dis<r*le)			//このloopは自分自身も通過するから、dis!=0は必要
								{
									double F=a*dis*dis*dis+b*dis*dis+d;
									Fx[k]-=F*x/dis;					//Fの値が正のときは斥力なので、-=にする
									Fy[k]-=F*y/dis;
									Fz[k]-=F*z/dis;
									Fx[J]+=F*x/dis;					//相手粒子の力もここで計算。符号は反転させる
									Fy[J]+=F*y/dis;
									Fz[J]+=F*z/dis;
									double K=3*a*dis*dis+2*b*dis;//バネ係数 力の式の微分に相当
									K=sqrt(K*K);					//正の値が欲しい。だから負のときに備えて正に変換
									KX[k]+=K*x*x/(dis*dis);			//kを各方向に分配。ここで、常に正の量が分配されるようにx*x/(dis*dis)となっている
									KY[k]+=K*y*y/(dis*dis);
									KZ[k]+=K*z*z/(dis*dis);
									KX[J]+=K*x*x/(dis*dis);			//kを相手粒子にも分配
									KY[J]+=K*y*y/(dis*dis);
									KZ[J]+=K*z*z/(dis*dis);
								}
							}
							if(j<BendID && j>=BstartID)
							{
								double x=PART[j].Get_X()-PART[i].Get_X();
								double y=PART[j].Get_Y()-PART[i].Get_Y();
								double z=PART[j].Get_Z()-PART[i].Get_Z();
								double dis=sqrt(x*x+y*y+z*z);
								if(dis<r*le && dis>0)			//このloopは自分自身は通過しない、dis!=0は不要
								{
									double F=a*dis*dis*dis+b*dis*dis+d;
									Fx[k]-=F*x/dis;					//Fの値が正のときは斥力なので、-=にする
									Fy[k]-=F*y/dis;
									Fz[k]-=F*z/dis;
									double K=3*a*dis*dis+2*b*dis;//バネ係数 力の式の微分に相当
									K=sqrt(K*K);					//正の値が欲しい。だから負のときに備えて正に変換
									KX[k]+=K*x*x/(dis*dis);			//kを各方向に分配。ここで、常に正の量が分配されるようにx*x/(dis*dis)となっている
									KY[k]+=K*y*y/(dis*dis);
									KZ[k]+=K*z*z/(dis*dis);
								}
							}
						}
					}
				}
			}
			//visX[k]=1.414*sqrt(KX[k]);//このように各軸方向の粘性係数を決める。文献「物理モデルによる自動メッシュ分割」P6参照。ただし質量は1としている。
			//visY[k]=1.414*sqrt(KY[k]);
			//visZ[k]=1.414*sqrt(KZ[k]);
			visX[k]=1.414*sqrt(KX[k]);//このように各軸方向の粘性係数を決める。文献「物理モデルによる自動メッシュ分割」P6参照。ただし質量は1としている。
			visY[k]=1.414*sqrt(KY[k]);
			visZ[k]=1.414*sqrt(KZ[k]);
			Ax[k]=(Fx[k]-visX[k]*U[k]);
			Ay[k]=(Fy[k]-visY[k]*V[k]);
			Az[k]=(Fz[k]-visZ[k]*W[k]);
		}//各粒子の加速度が求まった。
		
		if(t==0)	//最初のステップ時にdtを決定
		{
			double MaxAccel=0;
			for(int k=0;k<newN;k++)
			{
				double accel2=Ax[k]*Ax[k]+Ay[k]*Ay[k]+Az[k]*Az[k];
				if(accel2>MaxAccel) MaxAccel=accel2;
			}
			MaxAccel=sqrt(MaxAccel);//最大加速度が求まった
			if(MaxAccel!=0)
			{
				dt=sqrt(0.02*le/MaxAccel);
			}
		}

		for(int k=0;k<newN;k++)//速度と位置の更新
		{
			int i=beforeN+k;
			double u=U[k];
			double v=V[k];
			double w=W[k];
			U[k]+=dt*Ax[k];
			V[k]+=dt*Ay[k];
			W[k]+=dt*Az[k];
			PART[i].Add(dt*(U[k]+u)*0.5, dt*(V[k]+v)*0.5, dt*(W[k]+w)*0.5);
		}

		//再近接距離がle以下の場合はこれを修正
		for(int k=0;k<newN;k++)
		{
			int i=beforeN+k;					//対応する粒子番号
			int G_id=index[k];				//格納する格子番号
			double mindis=le;
			int J=k;						//最近接距離の相手粒子
			for(int II=G_id-1;II<=G_id+1;II++)
			{       
				for(int JJ=-1*grid_sizeX;JJ<=grid_sizeX;JJ+=grid_sizeX)
				{
					for(int KK=-1*plane_SIZE;KK<=plane_SIZE;KK+=plane_SIZE)
					{
						int M_id=II+JJ+KK;
						for(int L=0;L<MESH[M_id].size();L++)
						{
							int j=MESH[M_id][L];
							double x=PART[j].Get_X()-PART[i].Get_X();
							double y=PART[j].Get_Y()-PART[i].Get_Y();
							double z=PART[j].Get_Z()-PART[i].Get_Z();
							double dis=sqrt(x*x+y*y+z*z);
							if(dis<mindis && i!=j)
							{
								mindis=dis;
								J=j;
							}
						}
					}
				}
			}
			if(J!=i && J<beforeN)//leより近接している相手が境界粒子なら
			{
				double L=le-mindis;//開くべき距離
				double dX=PART[J].Get_X()-PART[i].Get_X();
				double dY=PART[J].Get_Y()-PART[i].Get_Y();
				double dZ=PART[J].Get_Z()-PART[i].Get_Z();
				PART[i].Add(-dX/mindis*L, -dY/mindis*L, -dZ/mindis*L);
			}
			else if(J!=i && J>=beforeN)//leより近接している相手が内部粒子なら
			{
				double L=0.5*(le-mindis);//開くべき距離
				double dX=PART[J].Get_X()-PART[i].Get_X();
				double dY=PART[J].Get_Y()-PART[i].Get_Y();
				double dZ=PART[J].Get_Z()-PART[i].Get_Z();
				PART[i].Add(-dX/mindis*L, -dY/mindis*L, -dZ/mindis*L);
				PART[J].Add(dX/mindis*L, dY/mindis*L, dZ/mindis*L);
			}
		}//////////*/
	}/////MD終了

	delete [] index;
	delete [] MESH;
}
Ejemplo n.º 20
0
int
Stokhos::GMRESDivisionExpansionStrategy<ordinal_type,value_type,node_type>::
GMRES(const Teuchos::SerialDenseMatrix<int, double> &  A, Teuchos::SerialDenseMatrix<int,double> &  X, const Teuchos::SerialDenseMatrix<int,double> &   B, int max_iter, double tolerance, int prec_iter, int order, int dim, int PrecNum, const Teuchos::SerialDenseMatrix<int, double> & M, int diag)
{
    int n = A.numRows();
    int k = 1;
    double resid;
    Teuchos::SerialDenseMatrix<int, double> P(n,n);
    Teuchos::SerialDenseMatrix<int, double> Ax(n,1);
    Ax.multiply(Teuchos::NO_TRANS,Teuchos::NO_TRANS,1.0, A, X, 0.0);
    Teuchos::SerialDenseMatrix<int, double> r0(B);
    r0-=Ax;
    resid=r0.normFrobenius();
//define vector v=r/norm(r) where r=b-Ax
    Teuchos::SerialDenseMatrix<int, double> v(n,1);
    r0.scale(1/resid);
    Teuchos::SerialDenseMatrix<int, double> h(1,1);
//Matrix of orthog basis vectors V
    Teuchos::SerialDenseMatrix<int, double> V(n,1);
//Set v=r0/norm(r0) to be 1st col of V
    for (int i=0; i<n; i++) {
        V(i,0)=r0(i,0);
    }
    //right hand side
    Teuchos::SerialDenseMatrix<int, double> bb(1,1);
    bb(0,0)=resid;
    Teuchos::SerialDenseMatrix<int, double> w(n,1);
    Teuchos::SerialDenseMatrix<int, double> c;
    Teuchos::SerialDenseMatrix<int, double> s;
    while (resid > tolerance && k < max_iter) {
        h.reshape(k+1,k);
        //Arnoldi iteration(Gram-Schmidt )
        V.reshape(n,k+1);
        //set vk to be kth col of V
        Teuchos::SerialDenseMatrix<int, double> vk(Teuchos::Copy, V, n,1,0,k-1);
        //Preconditioning step: solve Mz=vk
        Teuchos::SerialDenseMatrix<int, double> z(vk);
        if (PrecNum == 1) {
            Stokhos::DiagPreconditioner precond(M);
            precond.ApplyInverse(vk,z,prec_iter);
        }
        else if (PrecNum == 2) {
            Stokhos::JacobiPreconditioner precond(M);
            precond.ApplyInverse(vk,z,2);
        }
        else if (PrecNum == 3) {
            Stokhos::GSPreconditioner precond(M,1);
            precond.ApplyInverse(vk,z,1);
        }
        else if (PrecNum == 4) {
            Stokhos::SchurPreconditioner precond(M, order, dim, diag);
            precond.ApplyInverse(vk,z,prec_iter);
        }

        w.multiply(Teuchos::NO_TRANS, Teuchos::NO_TRANS, 1, A, z, 0.0);
        Teuchos::SerialDenseMatrix<int, double> vi(n,1);
        Teuchos::SerialDenseMatrix<int, double> ip(1,1);
        for (int i=0; i<k; i++) {
            //set vi to be ith col of V
            Teuchos::SerialDenseMatrix<int, double> vi(Teuchos::Copy, V, n,1,0,i);
            //Calculate inner product
            ip.multiply(Teuchos::TRANS, Teuchos::NO_TRANS, 1.0, vi, w, 0.0);
            h(i,k-1)= ip(0,0);
            //scale vi by h(i,k-1)
            vi.scale(ip(0,0));
            w-=vi;
        }
        h(k,k-1)=w.normFrobenius();
        w.scale(1.0/h(k,k-1));
        //add column vk+1=w to V
        for (int i=0; i<n; i++) {
            V(i,k)=w(i,0);
        }
        //Solve upper hessenberg least squares problem via Givens rotations
        //Compute previous Givens rotations
        for (int i=0; i<k-1; i++) {
            double q=c(i,0)*h(i,k-1)+s(i,0)*h(i+1,k-1);
            h(i+1,k-1)=-1*s(i,0)*h(i,k-1)+c(i,0)*h(i+1,k-1);
            h(i,k-1)=q;

        }
        //Compute next Givens rotations
        c.reshape(k,1);
        s.reshape(k,1);
        bb.reshape(k+1,1);
        double l = sqrt(h(k-1,k-1)*h(k-1,k-1)+h(k,k-1)*h(k,k-1));
        c(k-1,0)=h(k-1,k-1)/l;
        s(k-1,0)=h(k,k-1)/l;

        // Givens rotation on h and bb
        h(k-1,k-1)=l;
        h(k,k-1)=0;

        bb(k,0)=-s(k-1,0)*bb(k-1,0);
        bb(k-1,0)=c(k-1,0)*bb(k-1,0);

        //Determine residual
        resid = fabs(bb(k,0));
        k++;
    }
    //Extract upper triangular square matrix
    bb.reshape(h.numRows()-1 ,1);
    //Solve linear system
    int info;
    Teuchos::LAPACK<int, double> lapack;
    lapack.TRTRS('U', 'N', 'N', h.numRows()-1, 1, h.values(), h.stride(), bb.values(), bb.stride(),&info);
    Teuchos::SerialDenseMatrix<int, double> ans(X);
    V.reshape(n,k-1);
    ans.multiply(Teuchos::NO_TRANS, Teuchos::NO_TRANS, 1.0, V, bb, 0.0);
    if (PrecNum == 1) {
        Stokhos::DiagPreconditioner precond(M);
        precond.ApplyInverse(ans,ans,prec_iter);
    }
    else if (PrecNum == 2) {
        Stokhos::JacobiPreconditioner precond(M);
        precond.ApplyInverse(ans,ans,2);
    }
    else if (PrecNum == 3) {
        Stokhos::GSPreconditioner precond(M,1);
        precond.ApplyInverse(ans,ans,1);
    }
    else if (PrecNum == 4) {
        Stokhos::SchurPreconditioner precond(M, order, dim, diag);
        precond.ApplyInverse(ans,ans,prec_iter);
    }
    X+=ans;

    std::cout << "iteration count=  " << k-1 << std::endl;


    return 0;
}
Ejemplo n.º 21
0
inline bool TRobustRegressionL1PD(
  const MATRIX_TYPE& A,
  const Eigen::Matrix<REAL, Eigen::Dynamic, 1>& y,
  Eigen::Matrix<REAL, Eigen::Dynamic, 1>& xp,
  REAL pdtol=1e-3, unsigned pdmaxiter=50)
{
  typedef Eigen::Matrix<REAL, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> Matrix;
  typedef Eigen::Matrix<REAL, Eigen::Dynamic, 1> Vector;
  const unsigned M = (unsigned)y.size();
  const unsigned N = (unsigned)xp.size();
  assert(A.rows() == M && A.cols() == N);

  const REAL alpha(0.01);
  const REAL beta(0.5);
  const REAL mu(10);

  Vector x(xp);
  Vector Ax(A*x);
  Vector tmpM1(y-Ax);
  Vector tmpM2(-tmpM1);
  Vector tmpM3(tmpM1.cwiseAbs()), tmpM4(M);
  Vector u = (tmpM3*REAL(0.95)).array() + tmpM3.maxCoeff()*REAL(0.10);
  Vector fu1 = tmpM2-u;
  Vector fu2 = tmpM1-u;

  Vector lamu1(M), lamu2(M);
  for (unsigned i=0; i<M; ++i) {
    lamu1(i) = -1.0/fu1(i);
    lamu2(i) = -1.0/fu2(i);
  }
  const MATRIX_TYPE At(A.transpose());
  Vector Atv(At*(lamu1-lamu2));
  REAL AtvNormSq = Atv.squaredNorm();
  Vector rdual((-lamu1-lamu2).array() + REAL(1));
  REAL rdualNormSq = rdual.squaredNorm();

  Vector w2(M), sig1(M), sig2(M), sigx(M), dx(N), up(N), Atdv(N);
  Vector Axp(M), Atvp(M);
  Vector &Adx(sigx), &du(w2), &w1p(dx);
  Matrix H11p(N,N);
  Vector &dlamu1(tmpM3), &dlamu2(tmpM4);
  for (unsigned pditer=0; pditer<pdmaxiter; ++pditer) {
    // surrogate duality gap
    const REAL sdg(-(fu1.dot(lamu1) + fu2.dot(lamu2)));
    if (sdg < pdtol)
      break;
    const REAL tau(mu*2*M/sdg);
    const REAL inv_tau = REAL(-1)/tau;
    tmpM1 = (-lamu1.cwiseProduct(fu1)).array() + inv_tau;
    tmpM2 = (-lamu2.cwiseProduct(fu2)).array() + inv_tau;
    const REAL resnorm = sqrt(AtvNormSq + rdualNormSq + tmpM1.squaredNorm() + tmpM2.squaredNorm());

    for (unsigned i=0; i<M; ++i) {
      REAL& tmpM3i = tmpM3(i);
      tmpM3i = inv_tau/fu1(i);
      REAL& tmpM4i = tmpM4(i);
      tmpM4i = inv_tau/fu2(i);
      w2(i) = tmpM3i + tmpM4i - REAL(1);
    }

    tmpM1 = lamu1.cwiseQuotient(fu1);
    tmpM2 = lamu2.cwiseQuotient(fu2);
    sig1 = -tmpM1 - tmpM2;
    sig2 = tmpM1 - tmpM2;
    sigx = sig1 - sig2.cwiseAbs2().cwiseQuotient(sig1);

    H11p = At*(Eigen::DiagonalMatrix<REAL,Eigen::Dynamic>(sigx)*A);
    w1p = At*(tmpM4 - tmpM3 - (sig2.cwiseQuotient(sig1).cwiseProduct(w2)));

    // optimized solver as A is positive definite and symmetric
    dx = H11p.ldlt().solve(w1p);

    Adx = A*dx;

    du = (w2 - sig2.cwiseProduct(Adx)).cwiseQuotient(sig1);

    dlamu1 = -tmpM1.cwiseProduct(Adx-du) - lamu1 + tmpM3;
    dlamu2 =  tmpM2.cwiseProduct(Adx+du) - lamu2 + tmpM4;
    Atdv = At*(dlamu1-dlamu2);

    // make sure that the step is feasible: keeps lamu1,lamu2 > 0, fu1,fu2 < 0
    REAL s(1);
    for (unsigned i=0; i<M; ++i) {
      REAL& dlamu1i = dlamu1(i);
      if (dlamu1i < 0) {
        const REAL tmp = -lamu1(i)/dlamu1i;
        if (s > tmp)
          s = tmp;
      }
      REAL& dlamu2i = dlamu2(i);
      if (dlamu2i < 0) {
        const REAL tmp = -lamu2(i)/dlamu2i;
        if (s > tmp)
          s = tmp;
      }
    }
    for (unsigned i=0; i<M; ++i) {
      REAL& Adxi = Adx(i);
      REAL& dui = du(i);
      REAL Adx_du = Adxi-dui;
      if (Adx_du > 0) {
        const REAL tmp = -fu1(i)/Adx_du;
        if (s > tmp)
          s = tmp;
      }
      Adx_du = -Adxi-dui;
      if (Adx_du > 0) {
        const REAL tmp = -fu2(i)/Adx_du;
        if (s > tmp)
          s = tmp;
      }
    }
    s *= REAL(0.99);

    // backtrack
    lamu1 += s*dlamu1;  lamu2 += s*dlamu2;
    rdual = (-lamu1-lamu2).array() + REAL(1);
    rdualNormSq = rdual.squaredNorm();
    bool suffdec = false;
    unsigned backiter = 0;
    do {
      xp = x + s*dx;  up = u + s*du;
      Axp = Ax + s*Adx;  Atvp = Atv + s*Atdv;
      fu1 = Axp - y - up;  fu2 = -Axp + y - up;
      AtvNormSq = Atvp.squaredNorm();
      tmpM1 = (-lamu1.cwiseProduct(fu1)).array() + inv_tau;
      tmpM2 = (-lamu2.cwiseProduct(fu2)).array() + inv_tau;
      const REAL newresnorm = sqrt(AtvNormSq + rdualNormSq + tmpM1.squaredNorm() + tmpM2.squaredNorm());
      suffdec = (newresnorm <= (REAL(1)-alpha*s)*resnorm);
      s = beta*s;
      if (++backiter > 32) {
        //("error: stuck backtracking, returning last iterate"); // see Section 4 of notes for more information
        xp.swap(x);
        return false;
      }
    } while (!suffdec);

    // next iteration
    x.swap(xp);  u.swap(up);
    Ax.swap(Axp);  Atv.swap(Atvp);
  }
  return true;
}
Ejemplo n.º 22
0
VEC	*iter_lsqr(ITER *ip)
#endif
{
    STATIC VEC	*u = VNULL, *v = VNULL, *w = VNULL, *tmp = VNULL;
    Real	alpha, beta, phi, phi_bar;
    Real rho, rho_bar, rho_max, theta, nres;
    Real	s, c;	/* for Givens' rotations */
    int  m, n;

    if ( ! ip || ! ip->b || !ip->Ax || !ip->ATx )
        error(E_NULL,"iter_lsqr");
    if ( ip->x == ip->b )
        error(E_INSITU,"iter_lsqr");
    if (!ip->stop_crit || !ip->x)
        error(E_NULL,"iter_lsqr");

    if ( ip->eps <= 0.0 ) ip->eps = MACHEPS;

    m = ip->b->dim;
    n = ip->x->dim;

    u = v_resize(u,(unsigned int)m);
    v = v_resize(v,(unsigned int)n);
    w = v_resize(w,(unsigned int)n);
    tmp = v_resize(tmp,(unsigned int)n);

    MEM_STAT_REG(u,TYPE_VEC);
    MEM_STAT_REG(v,TYPE_VEC);
    MEM_STAT_REG(w,TYPE_VEC);
    MEM_STAT_REG(tmp,TYPE_VEC);

    if (ip->x != VNULL) {
        ip->Ax(ip->A_par,ip->x,u);    		/* u = A*x */
        v_sub(ip->b,u,u);				/* u = b-A*x */
    }
    else {  /* ip->x == 0 */
        ip->x = v_get(ip->b->dim);
        ip->shared_x = FALSE;
        v_copy(ip->b,u);                       /* u = b */
    }

    beta = v_norm2(u);
    if ( beta == 0.0 ) return ip->x;

    sv_mlt(1.0/beta,u,u);
    (ip->ATx)(ip->AT_par,u,v);
    alpha = v_norm2(v);
    if ( alpha == 0.0 ) return ip->x;

    sv_mlt(1.0/alpha,v,v);
    v_copy(v,w);
    phi_bar = beta;
    rho_bar = alpha;

    rho_max = 1.0;
    for (ip->steps = 0; ip->steps <= ip->limit; ip->steps++) {

        tmp = v_resize(tmp,m);
        (ip->Ax)(ip->A_par,v,tmp);

        v_mltadd(tmp,u,-alpha,u);
        beta = v_norm2(u);
        sv_mlt(1.0/beta,u,u);

        tmp = v_resize(tmp,n);
        (ip->ATx)(ip->AT_par,u,tmp);
        v_mltadd(tmp,v,-beta,v);
        alpha = v_norm2(v);
        sv_mlt(1.0/alpha,v,v);

        rho = sqrt(rho_bar*rho_bar+beta*beta);
        if ( rho > rho_max )
            rho_max = rho;
        c   = rho_bar/rho;
        s   = beta/rho;
        theta   =  s*alpha;
        rho_bar = -c*alpha;
        phi     =  c*phi_bar;
        phi_bar =  s*phi_bar;

        /* update ip->x & w */
        if ( rho == 0.0 )
            error(E_BREAKDOWN,"iter_lsqr");
        v_mltadd(ip->x,w,phi/rho,ip->x);
        v_mltadd(v,w,-theta/rho,w);

        nres = fabs(phi_bar*alpha*c)*rho_max;

        if (ip->info) ip->info(ip,nres,w,VNULL);
        if (ip->steps == 0) ip->init_res = nres;
        if ( ip->stop_crit(ip,nres,w,VNULL) ) break;
    }

#ifdef THREADSAFE
    V_FREE(u);
    V_FREE(v);
    V_FREE(w);
    V_FREE(tmp);
#endif

    return ip->x;
}
void
TimeIterationPolicyNonlinear<mesh_Type, AssemblyPolicy, SolverPolicy>::
iterate ( vectorPtr_Type solution,
          bcContainerPtr_Type bchandler,
          const Real& currentTime )
{
    int subiter = 0;

    Real normRhs ( 0.0 );
    Real nonLinearResidual ( 0.0 );
    Real rhsIterNorm ( 0.0 );

    do
    {
        //
        // STEP 1: Updating the system
        //
        displayer().leaderPrint ( "Updating the system... " );
        *M_rhs = 0.0;
        M_systemMatrix.reset ( new matrix_Type ( *M_solutionMap ) );
        AssemblyPolicy::assembleSystem ( M_systemMatrix, M_rhs, solution, SolverPolicy::preconditioner() );
        displayer().leaderPrint ( "done\n" );

        //
        // STEP 2: Applying the boundary conditions
        //
        displayer().leaderPrint ( "Applying BC... " );
        bcManage ( *M_systemMatrix, *M_rhs, *uFESpace()->mesh(), uFESpace()->dof(), *bchandler, uFESpace()->feBd(), 1.0, currentTime );
        M_systemMatrix->globalAssemble();
        displayer().leaderPrint ( "done\n" );

        // Norm of the rhs needed for the nonlinear convergence test
        if ( subiter == 0 )
        {
            normRhs = M_rhs->norm2();
        }

        //
        // STEP 3: Computing the residual
        //

        // Computing the RHS as RHS=b-Ax_k
        vector_Type Ax ( solution->map() );
        M_systemMatrix->matrixPtr()->Apply ( solution->epetraVector(), Ax.epetraVector() );

        Ax.epetraVector().Update (-1, M_rhs->epetraVector(), 1);
        nonLinearResidual = Ax.norm2();

        displayer().leaderPrint ( "Nonlinear residual          : ", nonLinearResidual, "\n" );
        displayer().leaderPrint ( "Nonlinear residual (scaled) : ", nonLinearResidual / normRhs, "\n" );

        if ( nonLinearResidual > M_nonLinearTolerance * normRhs )
        {
            displayer().leaderPrint ( "---\nSubiteration [", ++subiter, "]\n" );

            // Extra information if we want to know the exact residual
            if ( M_computeResidual )
            {
                rhsIterNorm = M_rhs->norm2();
            }

            //
            // Solving the system
            //
            displayer().leaderPrint ( "Solving the system... \n" );
            *solution = 0.0;
            SolverPolicy::solve ( M_systemMatrix, M_rhs, solution );
            // int numIter = SolverPolicy::solve( M_systemMatrix, M_rhs, solution );
            // numIterSum += numIter; //

            if ( M_computeResidual )
            {
                vector_Type Ax ( solution->map() );
                vector_Type res ( *M_rhs );
                M_systemMatrix->matrixPtr()->Apply ( solution->epetraVector(), Ax.epetraVector() );
                res.epetraVector().Update ( -1, Ax.epetraVector(), 1 );
                Real residual;
                res.norm2 ( &residual );
                residual /= rhsIterNorm;
                displayer().leaderPrint ( "Scaled residual: ", residual, "\n" );
            }
        }
    }
    while ( nonLinearResidual > M_nonLinearTolerance * normRhs );

    displayer().leaderPrint ( "Nonlinear iterations           : ", subiter, "\n" );
}
ordinal_type
Stokhos::CGDivisionExpansionStrategy<ordinal_type,value_type,node_type>::
CG(const Teuchos::SerialDenseMatrix<ordinal_type, value_type> & A, 
   Teuchos::SerialDenseMatrix<ordinal_type,value_type> & X, 
   const Teuchos::SerialDenseMatrix<ordinal_type,value_type> & B, 
   ordinal_type max_iter, 
   value_type tolerance, 
   ordinal_type prec_iter, 
   ordinal_type order , 
   ordinal_type m, 
   ordinal_type PrecNum, 
   const Teuchos::SerialDenseMatrix<ordinal_type, value_type> & M, 
   ordinal_type diag)

{
  ordinal_type n = A.numRows();
  ordinal_type k=0;
  value_type resid;
  Teuchos::SerialDenseMatrix<ordinal_type, value_type> Ax(n,1);
  Ax.multiply(Teuchos::NO_TRANS,Teuchos::NO_TRANS,1.0, A, X, 0.0);
  Teuchos::SerialDenseMatrix<ordinal_type, value_type> r(Teuchos::Copy,B);
  r-=Ax;
  resid=r.normFrobenius();
  Teuchos::SerialDenseMatrix<ordinal_type, value_type> p(r);
  Teuchos::SerialDenseMatrix<ordinal_type, value_type> rho(1,1);
  Teuchos::SerialDenseMatrix<ordinal_type, value_type> oldrho(1,1);
  Teuchos::SerialDenseMatrix<ordinal_type, value_type> pAp(1,1);
  Teuchos::SerialDenseMatrix<ordinal_type, value_type> Ap(n,1);
  value_type b;
  value_type a;
  while (resid > tolerance && k < max_iter){
    Teuchos::SerialDenseMatrix<ordinal_type, value_type> z(r);
    //Solve Mz=r
    if (PrecNum != 0){
      if (PrecNum == 1){
	Stokhos::DiagPreconditioner<ordinal_type, value_type> precond(M);
	precond.ApplyInverse(r,z,prec_iter);
      }
      else if (PrecNum == 2){
	Stokhos::JacobiPreconditioner<ordinal_type, value_type> precond(M);
	precond.ApplyInverse(r,z,2);
      }
      else if (PrecNum == 3){
	Stokhos::GSPreconditioner<ordinal_type, value_type> precond(M,0);
	precond.ApplyInverse(r,z,1);
      }
      else if (PrecNum == 4){
	Stokhos::SchurPreconditioner<ordinal_type, value_type> precond(M, order, m, diag);
	precond.ApplyInverse(r,z,prec_iter);            
      }
    }
    rho.multiply(Teuchos::TRANS,Teuchos::NO_TRANS,1.0, r, z, 0.0);
    

    if (k==0){
      p.assign(z);
      rho.multiply(Teuchos::TRANS, Teuchos::NO_TRANS, 1.0, r, z, 0.0);  
    }
    else {
      b=rho(0,0)/oldrho(0,0);
      p.scale(b);
      p+=z; 
    }
    Ap.multiply(Teuchos::NO_TRANS,Teuchos::NO_TRANS,1.0, A, p, 0.0);
    pAp.multiply(Teuchos::TRANS,Teuchos::NO_TRANS,1.0, p, Ap, 0.0);
    a=rho(0,0)/pAp(0,0);
    Teuchos::SerialDenseMatrix<ordinal_type, value_type> scalep(p);
    scalep.scale(a);
    X+=scalep;
    Ap.scale(a);
    r-=Ap;
    oldrho.assign(rho);
    resid=r.normFrobenius();
    k++;
  }                      
 
  //std::cout << "iteration count  " << k << std::endl;
  return 0; 
}
Ejemplo n.º 25
0
VEC  *iter_cgne(ITER *ip)
#endif
{
    STATIC VEC *r = VNULL, *p = VNULL, *q = VNULL, *z = VNULL;
    Real	alpha, beta, inner, old_inner, nres;
    VEC *rr1;   /* pointer only */

    if (ip == INULL)
        error(E_NULL,"iter_cgne");
    if (!ip->Ax || ! ip->ATx || !ip->b)
        error(E_NULL,"iter_cgne");
    if ( ip->x == ip->b )
        error(E_INSITU,"iter_cgne");
    if (!ip->stop_crit)
        error(E_NULL,"iter_cgne");

    if ( ip->eps <= 0.0 ) ip->eps = MACHEPS;

    r = v_resize(r,ip->b->dim);
    p = v_resize(p,ip->b->dim);
    q = v_resize(q,ip->b->dim);

    MEM_STAT_REG(r,TYPE_VEC);
    MEM_STAT_REG(p,TYPE_VEC);
    MEM_STAT_REG(q,TYPE_VEC);

    z = v_resize(z,ip->b->dim);
    MEM_STAT_REG(z,TYPE_VEC);

    if (ip->x) {
        if (ip->x->dim != ip->b->dim)
            error(E_SIZES,"iter_cgne");
        ip->Ax(ip->A_par,ip->x,p);    		/* p = A*x */
        v_sub(ip->b,p,z);		 		/* z = b - A*x */
    }
    else {  /* ip->x == 0 */
        ip->x = v_get(ip->b->dim);
        ip->shared_x = FALSE;
        v_copy(ip->b,z);
    }
    rr1 = z;
    if (ip->Bx) {
        (ip->Bx)(ip->B_par,rr1,p);
        rr1 = p;
    }
    (ip->ATx)(ip->AT_par,rr1,r);		/* r = A^T*B*(b-A*x)  */


    old_inner = 0.0;
    for ( ip->steps = 0; ip->steps <= ip->limit; ip->steps++ )
    {
        rr1 = r;
        if ( ip->Bx ) {
            (ip->Bx)(ip->B_par,r,z);		/* rr = B*r */
            rr1 = z;
        }

        inner = in_prod(r,rr1);
        nres = sqrt(fabs(inner));
        if (ip->info) ip->info(ip,nres,r,rr1);
        if (ip->steps == 0) ip->init_res = nres;
        if ( ip->stop_crit(ip,nres,r,rr1) ) break;

        if ( ip->steps )	/* if ( ip->steps > 0 ) ... */
        {
            beta = inner/old_inner;
            p = v_mltadd(rr1,p,beta,p);
        }
        else		/* if ( ip->steps == 0 ) ... */
        {
            beta = 0.0;
            p = v_copy(rr1,p);
            old_inner = 0.0;
        }
        (ip->Ax)(ip->A_par,p,q);     /* q = A*p */
        if (ip->Bx) {
            (ip->Bx)(ip->B_par,q,z);
            (ip->ATx)(ip->AT_par,z,q);
            rr1 = q;			/* q = A^T*B*A*p */
        }
        else {
            (ip->ATx)(ip->AT_par,q,z);	/* z = A^T*A*p */
            rr1 = z;
        }

        alpha = inner/in_prod(rr1,p);
        v_mltadd(ip->x,p,alpha,ip->x);
        v_mltadd(r,rr1,-alpha,r);
        old_inner = inner;
    }

#ifdef THREADSAFE
    V_FREE(r);
    V_FREE(p);
    V_FREE(q);
    V_FREE(z);
#endif

    return ip->x;
}
Ejemplo n.º 26
0
// CG
int CG(const  Teuchos::SerialDenseMatrix<int, double> &  A, Teuchos::SerialDenseMatrix<int,double>   X,const Teuchos::SerialDenseMatrix<int,double> &   B, int max_iter, double tolerance, Stokhos::DiagPreconditioner<int,double> prec)

{
  int n; 
  int k=0;
  double resid;
  
  n=A.numRows();
  std::cout << "A= " << A << std::endl;
  std::cout << "B= " << B << std::endl;
  Teuchos::SerialDenseMatrix<int, double> Ax(n,1);
  Ax.multiply(Teuchos::NO_TRANS,Teuchos::NO_TRANS,1.0, A, X, 0.0);

  Teuchos::SerialDenseMatrix<int, double> r(B);
  r-=Ax;  
  resid=r.normFrobenius(); 
  Teuchos::SerialDenseMatrix<int, double> rho(1,1);
  Teuchos::SerialDenseMatrix<int, double> oldrho(1,1);
  Teuchos::SerialDenseMatrix<int, double> pAp(1,1);
  Teuchos::SerialDenseMatrix<int, double> Ap(n,1);
  
  double b;
  double a;
  Teuchos::SerialDenseMatrix<int, double> p(r);

  
 
  while (resid > tolerance && k < max_iter){
 
     Teuchos::SerialDenseMatrix<int, double> z(r);
     
     //z=M-1r
//     prec.ApplyInverse(r,z);

     rho.multiply(Teuchos::TRANS,Teuchos::NO_TRANS,1.0, r, z, 0.0);
  
     if (k==0){
       p.assign(z);
       rho.multiply(Teuchos::TRANS, Teuchos::NO_TRANS, 1.0, r, z, 0.0);
      }  
      else {
        b=rho(0,0)/oldrho(0,0);
        p.scale(b);
        p+=z;
      }
      Ap.multiply(Teuchos::NO_TRANS,Teuchos::NO_TRANS,1.0, A, p, 0.0);
      pAp.multiply(Teuchos::TRANS,Teuchos::NO_TRANS,1.0, p, Ap, 0.0);
      a=rho(0,0)/pAp(0,0);
      Teuchos::SerialDenseMatrix<int, double> scalep(p);
      scalep.scale(a);
      X+=scalep;
      Ap.scale(a);
      r-=Ap;
      oldrho.assign(rho);
      resid=r.normFrobenius();
   
 
     k++;
  } 
  
 std::cout << "X=  " << X << std::endl;

 return 0;
}
Ejemplo n.º 27
0
VEC	*iter_cgs(ITER *ip, VEC *r0)
#endif
{
    STATIC VEC  *p = VNULL, *q = VNULL, *r = VNULL, *u = VNULL;
    STATIC VEC  *v = VNULL, *z = VNULL;
    VEC  *tmp;
    Real	alpha, beta, nres, rho, old_rho, sigma, inner;

    if (ip == INULL)
        error(E_NULL,"iter_cgs");
    if (!ip->Ax || !ip->b || !r0)
        error(E_NULL,"iter_cgs");
    if ( ip->x == ip->b )
        error(E_INSITU,"iter_cgs");
    if (!ip->stop_crit)
        error(E_NULL,"iter_cgs");
    if ( r0->dim != ip->b->dim )
        error(E_SIZES,"iter_cgs");

    if ( ip->eps <= 0.0 ) ip->eps = MACHEPS;

    p = v_resize(p,ip->b->dim);
    q = v_resize(q,ip->b->dim);
    r = v_resize(r,ip->b->dim);
    u = v_resize(u,ip->b->dim);
    v = v_resize(v,ip->b->dim);

    MEM_STAT_REG(p,TYPE_VEC);
    MEM_STAT_REG(q,TYPE_VEC);
    MEM_STAT_REG(r,TYPE_VEC);
    MEM_STAT_REG(u,TYPE_VEC);
    MEM_STAT_REG(v,TYPE_VEC);

    if (ip->Bx) {
        z = v_resize(z,ip->b->dim);
        MEM_STAT_REG(z,TYPE_VEC);
    }

    if (ip->x != VNULL) {
        if (ip->x->dim != ip->b->dim)
            error(E_SIZES,"iter_cgs");
        ip->Ax(ip->A_par,ip->x,v);    		/* v = A*x */
        if (ip->Bx) {
            v_sub(ip->b,v,v);			/* v = b - A*x */
            (ip->Bx)(ip->B_par,v,r);		/* r = B*(b-A*x) */
        }
        else v_sub(ip->b,v,r);			/* r = b-A*x */
    }
    else {  /* ip->x == 0 */
        ip->x = v_get(ip->b->dim);		/* x == 0 */
        ip->shared_x = FALSE;
        if (ip->Bx) (ip->Bx)(ip->B_par,ip->b,r);    /* r = B*b */
        else v_copy(ip->b,r);                       /* r = b */
    }

    v_zero(p);
    v_zero(q);
    old_rho = 1.0;

    for (ip->steps = 0; ip->steps <= ip->limit; ip->steps++) {

        inner = in_prod(r,r);
        nres = sqrt(fabs(inner));
        if (ip->steps == 0) ip->init_res = nres;

        if (ip->info) ip->info(ip,nres,r,VNULL);
        if ( ip->stop_crit(ip,nres,r,VNULL) ) break;

        rho = in_prod(r0,r);
        if ( old_rho == 0.0 )
            error(E_BREAKDOWN,"iter_cgs");
        beta = rho/old_rho;
        v_mltadd(r,q,beta,u);
        v_mltadd(q,p,beta,v);
        v_mltadd(u,v,beta,p);

        (ip->Ax)(ip->A_par,p,q);
        if (ip->Bx) {
            (ip->Bx)(ip->B_par,q,z);
            tmp = z;
        }
        else tmp = q;

        sigma = in_prod(r0,tmp);
        if ( sigma == 0.0 )
            error(E_BREAKDOWN,"iter_cgs");
        alpha = rho/sigma;
        v_mltadd(u,tmp,-alpha,q);
        v_add(u,q,v);

        (ip->Ax)(ip->A_par,v,u);
        if (ip->Bx) {
            (ip->Bx)(ip->B_par,u,z);
            tmp = z;
        }
        else tmp = u;

        v_mltadd(r,tmp,-alpha,r);
        v_mltadd(ip->x,v,alpha,ip->x);

        old_rho = rho;
    }

#ifdef THREADSAFE
    V_FREE(p);
    V_FREE(q);
    V_FREE(r);
    V_FREE(u);
    V_FREE(v);
    V_FREE(z);
#endif

    return ip->x;
}
Ejemplo n.º 28
0
int Amesos_Scalapack::Solve() { 
  
  if( debug_ == 1 ) std::cout << "Entering `Solve()'" << std::endl;
  
  NumSolve_++;
  
  Epetra_MultiVector   *vecX = Problem_->GetLHS() ; 
  Epetra_MultiVector   *vecB = Problem_->GetRHS() ; 
  
  //
  //  Compute the number of right hands sides 
  //  (and check that X and B have the same shape) 
  //
  int nrhs; 
  if ( vecX == 0 ) { 
    nrhs = 0 ;
    EPETRA_CHK_ERR( vecB != 0 ) ; 
  } else { 
    nrhs = vecX->NumVectors() ; 
    EPETRA_CHK_ERR( vecB->NumVectors() != nrhs ) ; 
  }
  
  Epetra_MultiVector *ScalapackB =0;
  Epetra_MultiVector *ScalapackX =0;
  //
  //  Extract Scalapack versions of X and B 
  //
  double *ScalapackXvalues ;
  
  Epetra_RowMatrix *RowMatrixA = dynamic_cast<Epetra_RowMatrix *>(Problem_->GetOperator());
  Time_->ResetStartTime(); // track time to broadcast vectors
  //
  //  Copy B to the scalapack version of B
  //
  const Epetra_Map &OriginalMap = RowMatrixA->RowMatrixRowMap();
  Epetra_MultiVector *ScalapackXextract = new Epetra_MultiVector( *VectorMap_, nrhs ) ; 
  Epetra_MultiVector *ScalapackBextract = new Epetra_MultiVector( *VectorMap_, nrhs ) ; 
  
  Epetra_Import ImportToScalapack( *VectorMap_, OriginalMap );
  ScalapackBextract->Import( *vecB, ImportToScalapack, Insert ) ;
  ScalapackB = ScalapackBextract ; 
  ScalapackX = ScalapackXextract ; 
  
  VecTime_ += Time_->ElapsedTime();
  
  //
  //  Call SCALAPACKs PDGETRS to perform the solve
  //
  
  int DescX[10];  
  
  ScalapackX->Scale(1.0, *ScalapackB) ;  
  
  int ScalapackXlda ; 
  
  Time_->ResetStartTime(); // tract time to solve
  
  //
  //  Setup DescX 
  //
  
  if( nrhs > nb_ ) {
    EPETRA_CHK_ERR( -2 );  
  }
  
  int Ierr[1] ; 
  Ierr[0] = 0 ; 
  const int zero = 0 ; 
  const int one = 1 ; 
  if ( iam_ < nprow_ * npcol_ ) {
    assert( ScalapackX->ExtractView( &ScalapackXvalues, &ScalapackXlda ) == 0 ) ; 
    
    if ( false ) std::cout << "Amesos_Scalapack.cpp: " << __LINE__ << " ScalapackXlda = "  <<  ScalapackXlda 
		      << " lda_ = "  << lda_ 
		      << " nprow_ = "  << nprow_ 
		      << " npcol_ = "  << npcol_ 
		      << " myprow_ = "  << myprow_ 
		      << " mypcol_ = "  << mypcol_ 
		      << " iam_ = "  << iam_ << std::endl ;
    if (  TwoD_distribution_ )    assert( mypcol_ >0 || EPETRA_MAX(ScalapackXlda,1) == lda_ ) ; 
    
    DESCINIT_F77(DescX, 
		 &NumGlobalElements_, 
		 &nrhs, 
		 &nb_,
		 &nb_,
		 &zero,
		 &zero,
		 &ictxt_,
		 &lda_,
		 Ierr ) ;
    assert( Ierr[0] == 0 ) ; 
    
    //
    //  For the 1D data distribution, we factor the transposed 
    //  matrix, hence we must invert the sense of the transposition
    //
    char trans = 'N';
    if ( TwoD_distribution_ ) {
      if ( UseTranspose() ) trans = 'T' ;
    } else {
      
      if ( ! UseTranspose() ) trans = 'T' ;
    }
    
    if ( nprow_ * npcol_ == 1 ) { 
      DGETRS_F77(&trans,
		 &NumGlobalElements_,  
		 &nrhs, 
		 &DenseA_[0],
		 &lda_,
		 &Ipiv_[0],
		 ScalapackXvalues,
		 &lda_,
		 Ierr ) ;
    } else { 
      PDGETRS_F77(&trans,
		  &NumGlobalElements_,  
		  &nrhs, 
		  &DenseA_[0],
		  &one,
		  &one, 
		  DescA_,
		  &Ipiv_[0],
		  ScalapackXvalues,
		  &one,
		  &one, 
		  DescX,
		  Ierr ) ;
    }
  }
  
  SolTime_ += Time_->ElapsedTime();
  
  Time_->ResetStartTime();  // track time to broadcast vectors
  //
  //  Copy X back to the original vector
  // 
  Epetra_Import ImportFromScalapack( OriginalMap, *VectorMap_ );
  vecX->Import( *ScalapackX, ImportFromScalapack, Insert ) ;
  delete ScalapackBextract ;
  delete ScalapackXextract ;
  
  VecTime_ += Time_->ElapsedTime();
  
  //  All processes should return the same error code
  if ( nprow_ * npcol_ < Comm().NumProc() ) 
    Comm().Broadcast( Ierr, 1, 0 ) ; 
  
  // MS // compute vector norms
  if( ComputeVectorNorms_ == true || verbose_ == 2 ) {
    double NormLHS, NormRHS;
    for( int i=0 ; i<nrhs ; ++i ) {
      assert((*vecX)(i)->Norm2(&NormLHS)==0);
      assert((*vecB)(i)->Norm2(&NormRHS)==0);
      if( verbose_ && Comm().MyPID() == 0 ) {
	std::cout << "Amesos_Scalapack : vector " << i << ", ||x|| = " << NormLHS
	     << ", ||b|| = " << NormRHS << std::endl;
      }
    }
  }
  
  // MS // compute true residual
  if( ComputeTrueResidual_ == true || verbose_ == 2  ) {
    double Norm;
    Epetra_MultiVector Ax(vecB->Map(),nrhs);
    for( int i=0 ; i<nrhs ; ++i ) {
      (Problem_->GetMatrix()->Multiply(UseTranspose(), *((*vecX)(i)), Ax));
      (Ax.Update(1.0, *((*vecB)(i)), -1.0));
      (Ax.Norm2(&Norm));
      
      if( verbose_ && Comm().MyPID() == 0 ) {
	std::cout << "Amesos_Scalapack : vector " << i << ", ||Ax - b|| = " << Norm << std::endl;
      }
    }
  }
  
  return Ierr[0];
  
}
Ejemplo n.º 29
0
VEC	*iter_gmres(ITER *ip)
#endif
{
    STATIC VEC *u=VNULL, *r=VNULL, *rhs = VNULL;
    STATIC VEC *givs=VNULL, *givc=VNULL, *z = VNULL;
    STATIC MAT *Q = MNULL, *R = MNULL;
    VEC *rr, v, v1;   /* additional pointers (not real vectors) */
    int	i,j, done;
    Real	nres;
    /*   Real last_h;  */

    if (ip == INULL)
        error(E_NULL,"iter_gmres");
    if ( ! ip->Ax || ! ip->b )
        error(E_NULL,"iter_gmres");
    if ( ! ip->stop_crit )
        error(E_NULL,"iter_gmres");
    if ( ip->k <= 0 )
        error(E_BOUNDS,"iter_gmres");
    if (ip->x != VNULL && ip->x->dim != ip->b->dim)
        error(E_SIZES,"iter_gmres");
    if (ip->eps <= 0.0) ip->eps = MACHEPS;

    r = v_resize(r,ip->k+1);
    u = v_resize(u,ip->b->dim);
    rhs = v_resize(rhs,ip->k+1);
    givs = v_resize(givs,ip->k);  /* Givens rotations */
    givc = v_resize(givc,ip->k);

    MEM_STAT_REG(r,TYPE_VEC);
    MEM_STAT_REG(u,TYPE_VEC);
    MEM_STAT_REG(rhs,TYPE_VEC);
    MEM_STAT_REG(givs,TYPE_VEC);
    MEM_STAT_REG(givc,TYPE_VEC);

    R = m_resize(R,ip->k+1,ip->k);
    Q = m_resize(Q,ip->k,ip->b->dim);
    MEM_STAT_REG(R,TYPE_MAT);
    MEM_STAT_REG(Q,TYPE_MAT);

    if (ip->x == VNULL) {  /* ip->x == 0 */
        ip->x = v_get(ip->b->dim);
        ip->shared_x = FALSE;
    }

    v.dim = v.max_dim = ip->b->dim;      /* v and v1 are pointers to rows */
    v1.dim = v1.max_dim = ip->b->dim;  	/* of matrix Q */

    if (ip->Bx != (Fun_Ax)NULL) {    /* if precondition is defined */
        z = v_resize(z,ip->b->dim);
        MEM_STAT_REG(z,TYPE_VEC);
    }

    done = FALSE;
    for (ip->steps = 0; ip->steps < ip->limit; ) {

        /* restart */

        ip->Ax(ip->A_par,ip->x,u);    		/* u = A*x */
        v_sub(ip->b,u,u);		 		/* u = b - A*x */
        rr = u;				/* rr is a pointer only */

        if (ip->Bx) {
            (ip->Bx)(ip->B_par,u,z);            /* tmp = B*(b-A*x)  */
            rr = z;
        }

        nres = v_norm2(rr);
        if (ip->steps == 0) {
            if (ip->info) ip->info(ip,nres,VNULL,VNULL);
            ip->init_res = nres;
        }

        if ( nres == 0.0 ) {
            done = TRUE;
            break;
        }

        v.ve = Q->me[0];
        sv_mlt(1.0/nres,rr,&v);

        v_zero(r);
        v_zero(rhs);
        rhs->ve[0] = nres;

        for ( i = 0; i < ip->k && ip->steps < ip->limit; i++ ) {
            ip->steps++;
            v.ve = Q->me[i];
            (ip->Ax)(ip->A_par,&v,u);
            rr = u;
            if (ip->Bx) {
                (ip->Bx)(ip->B_par,u,z);
                rr = z;
            }

            if (i < ip->k - 1) {
                v1.ve = Q->me[i+1];
                v_copy(rr,&v1);
                for (j = 0; j <= i; j++) {
                    v.ve = Q->me[j];
                    /* r->ve[j] = in_prod(&v,rr); */
                    /* modified Gram-Schmidt algorithm */
                    r->ve[j] = in_prod(&v,&v1);
                    v_mltadd(&v1,&v,-r->ve[j],&v1);
                }

                r->ve[i+1] = nres = v_norm2(&v1);
                if (nres <= MACHEPS*ip->init_res) {
                    for (j = 0; j < i; j++)
                        rot_vec(r,j,j+1,givc->ve[j],givs->ve[j],r);
                    set_col(R,i,r);
                    done = TRUE;
                    break;
                }
                sv_mlt(1.0/nres,&v1,&v1);
            }
            else {  /* i == ip->k - 1 */
                /* Q->me[ip->k] need not be computed */

                for (j = 0; j <= i; j++) {
                    v.ve = Q->me[j];
                    r->ve[j] = in_prod(&v,rr);
                }

                nres = in_prod(rr,rr) - in_prod(r,r);
                if (sqrt(fabs(nres)) <= MACHEPS*ip->init_res) {
                    for (j = 0; j < i; j++)
                        rot_vec(r,j,j+1,givc->ve[j],givs->ve[j],r);
                    set_col(R,i,r);
                    done = TRUE;
                    break;
                }
                if (nres < 0.0) { /* do restart */
                    i--;
                    ip->steps--;
                    break;
                }
                r->ve[i+1] = sqrt(nres);
            }

            /* QR update */

            /* last_h = r->ve[i+1]; */ /* for test only */
            for (j = 0; j < i; j++)
                rot_vec(r,j,j+1,givc->ve[j],givs->ve[j],r);
            givens(r->ve[i],r->ve[i+1],&givc->ve[i],&givs->ve[i]);
            rot_vec(r,i,i+1,givc->ve[i],givs->ve[i],r);
            rot_vec(rhs,i,i+1,givc->ve[i],givs->ve[i],rhs);

            set_col(R,i,r);

            nres = fabs((double) rhs->ve[i+1]);
            if (ip->info) ip->info(ip,nres,VNULL,VNULL);
            if ( ip->stop_crit(ip,nres,VNULL,VNULL) ) {
                done = TRUE;
                break;
            }
        }

        /* use ixi submatrix of R */

        if (i >= ip->k) i = ip->k - 1;

        R = m_resize(R,i+1,i+1);
        rhs = v_resize(rhs,i+1);

        /* test only */
        /* test_gmres(ip,i,Q,R,givc,givs,last_h);  */

        Usolve(R,rhs,rhs,0.0); 	 /* solve a system: R*x = rhs */

        /* new approximation */

        for (j = 0; j <= i; j++) {
            v.ve = Q->me[j];
            v_mltadd(ip->x,&v,rhs->ve[j],ip->x);
        }

        if (done) break;

        /* back to old dimensions */

        rhs = v_resize(rhs,ip->k+1);
        R = m_resize(R,ip->k+1,ip->k);

    }

#ifdef THREADSAFE
    V_FREE(u);
    V_FREE(r);
    V_FREE(rhs);
    V_FREE(givs);
    V_FREE(givc);
    V_FREE(z);
    M_FREE(Q);
    M_FREE(R);
#endif

    return ip->x;
}
void Model :: MD_2D(double le,int BstartID,int beforeN,int newN)
{
	//分子動力学によりnewN個の粒子の位置を最適化 IDがBstartIDからBendIDまでのは境界粒子なので動かさない

	double region[2][2];	//解析領域

	/////////////////////解析領域の決定
	region[A_X][0]=100; region[A_X][1]=-100;
	region[A_Y][0]=100; region[A_Y][1]=-100;
	for(int i=BstartID;i<beforeN;i++)
	{
		if(PART[i].Get_X()<region[A_X][0]) region[A_X][0]=PART[i].Get_X();
		else if(PART[i].Get_X()>region[A_X][1]) region[A_X][1]=PART[i].Get_X();

		if(PART[i].Get_Y()<region[A_Y][0]) region[A_Y][0]=PART[i].Get_Y();
		else if(PART[i].Get_Y()>region[A_Y][1]) region[A_Y][1]=PART[i].Get_Y();
	}
	for(int D=0;D<2;D++)
	{
		region[D][0]-=5*le;	//少し領域を広めにとる
		region[D][1]+=5*le;
	}//////////////////////////

	//パラメータ
	double k0=1;
	double r=1.5;
	double dt=0.001;
	
	//力はax^3+bx^2+dの式を採用。文献[Bubble Mesh Automated Triangular Meshing of Non-Manifold Geometry by Sphere Packing]を参照
	double a=(r+1)/(2*r*r-r-1)*k0/(le*le);
	double b=-0.5*k0/le-1.5*a*le;
	double d=-a*le*le*le-b*le*le;
	/////////////
	int lastN=beforeN+newN;
	vector<double> Fx(newN);	//各粒子に働くX方向力
	vector<double> Fy(newN);	//各粒子に働くY方向力
	vector<double> Ax(newN,0);	//X方向加速度
	vector<double> Ay(newN,0);	//Y方向加速度
	vector<double> U(newN,0);	//X方向速度
	vector<double> V(newN,0);	//Y方向速度
	vector<double> visX(newN);	//X方向粘性係数
	vector<double> visY(newN);	//Y方向粘性係数
	//計算の高速化のために格子を形成 解析幅がr*leで割り切れるとは限らないので、はみ出したところは切り捨て。なので各軸とも正の方向には余裕を持つこと
	double grid_width=le*((int)(r+1));								//格子の幅。rを含む整数*le
	int grid_sizeX=(int)((region[A_X][1]-region[A_X][0])/grid_width);	//X方向の格子の個数
	int grid_sizeY=(int)((region[A_Y][1]-region[A_Y][0])/grid_width);
	int plane_SIZE=grid_sizeX*grid_sizeY;
	int *index=new int[newN];									//各内部粒子を含む格子番号
//	cout<<"ここっぽい"<<endl;
//	vector<int> *MESH=new vector<int>[plane_SIZE];				//各メッシュに格納される粒子ID格納
	vector<vector<int> > MESH;
	MESH.resize(plane_SIZE);
	for(int i=BstartID;i<beforeN;i++)	//まずは境界粒子を格子に格納
	{
		int xn=(int)((PART[i].Get_X()-region[A_X][0])/grid_width);	//X方向に何個目の格子か 
		int yn=(int)((PART[i].Get_Y()-region[A_Y][0])/grid_width);	//Y方向に何個目の格子か
		int number=yn*grid_sizeX+xn;					//粒子iを含む格子の番号
		MESH[number].push_back(i);
	}
	for(int k=0;k<newN;k++)	//つぎに内部粒子を格納
	{
		int i=beforeN+k;
		int xn=(int)((PART[i].Get_X()-region[A_X][0])/grid_width);//X方向に何個目の格子か 
		int yn=(int)((PART[i].Get_Y()-region[A_Y][0])/grid_width);//Y方向に何個目の格子か
		int number=yn*grid_sizeX+xn;					//粒子iを含む格子の番号
		MESH[number].push_back(i);
		index[k]=number;
	}//////////////////////////////////////////

	//計算開始
	for(int t=0;t<100;t++)
	{
		if(t%10==0 &&t>0)//MESHを作り直す
		{
			//まずはMESHを一度破壊する。
			for(int n=0;n<plane_SIZE;n++)
			{
				size_t size=MESH[n].size();
				for(int k=0;k<size;k++) MESH[n].pop_back();
			}
			
			for(int i=BstartID;i<beforeN;i++)	//まずは境界粒子を格子に格納
			{
				int xn=(int)((PART[i].Get_X()-region[A_X][0])/grid_width);	//X方向に何個目の格子か 
				int yn=(int)((PART[i].Get_Y()-region[A_Y][0])/grid_width);	//Y方向に何個目の格子か
				int number=yn*grid_sizeX+xn;					//粒子iを含む格子の番号
				MESH[number].push_back(i);
			}
			for(int k=0;k<newN;k++)	//つぎに内部粒子を格納
			{
				int i=beforeN+k;
				int xn=(int)((PART[i].Get_X()-region[A_X][0])/grid_width);//X方向に何個目の格子か 
				int yn=(int)((PART[i].Get_Y()-region[A_Y][0])/grid_width);//Y方向に何個目の格子か
				int number=yn*grid_sizeX+xn;					//粒子iを含む格子の番号
				MESH[number].push_back(i);
				index[k]=number;
			}
		}////////////

		for(int k=0;k<newN;k++)
		{
			Fx[k]=0; Fy[k]=0;					//初期化
			int i=beforeN+k;					//対応する粒子番号
			double kx=0;						//X方向バネ係数
			double ky=0;
			int G_id=index[k];				//格納する格子番号
			for(int II=G_id-1;II<=G_id+1;II++)
			{       
				for(int JJ=-1*grid_sizeX;JJ<=grid_sizeX;JJ+=grid_sizeX)
				{
					int M_id=II+JJ;
					for(int L=0;L<MESH[M_id].size();L++)
					{
						int j=MESH[M_id][L];
						double x=PART[j].Get_X()-PART[i].Get_X();
						double y=PART[j].Get_Y()-PART[i].Get_Y();
						double dis=sqrt(x*x+y*y);
						if(dis<r*le && dis!=0)			//このloopは自分自身も通過するから、dis!=0は必要
						{
							double F=a*dis*dis*dis+b*dis*dis+d;
							Fx[k]-=F*x/dis;					//Fの値が正のときは斥力なので、-=にする
							Fy[k]-=F*y/dis;
							double K=3*a*dis*dis+2*b*dis;//バネ係数 力の式の微分に相当
							K=sqrt(K*K);					//正の値が欲しい。だから負のときに備えて正に変換
							kx+=K*x*x/(dis*dis);			//kを各方向に分配。ここで、常に正の量が分配されるようにx*x/(dis*dis)となっている
							ky+=K*y*y/(dis*dis);
						}
					}
				}
			}
			visX[k]=1.414*sqrt(kx);//このように各軸方向の粘性係数を決める。文献「物理モデルによる自動メッシュ分割」P6参照。ただし質量は1としている。
			visY[k]=1.414*sqrt(ky);
			Ax[k]=(Fx[k]-visX[k]*U[k]);
			Ay[k]=(Fy[k]-visY[k]*V[k]);
		}//各粒子の加速度が求まった。
		
		if(t==0)	//最初のステップ時にdtを決定
		{
			double MaxAccel=0;
			for(int k=0;k<newN;k++)
			{
				double accel2=Ax[k]*Ax[k]+Ay[k]*Ay[k];
				if(accel2>MaxAccel) MaxAccel=accel2;
			}
			MaxAccel=sqrt(MaxAccel);//最大加速度が求まった
			dt=sqrt(0.02*le/MaxAccel);
		}

		for(int k=0;k<newN;k++)//速度と位置の更新
		{
			int i=beforeN+k;
			double u=U[k];
			double v=V[k];
			U[k]+=dt*Ax[k];
			V[k]+=dt*Ay[k];
			PART[i].Add(dt*(U[k]+u)*0.5, dt*(V[k]+v)*0.5, 0);	
		}

		//再近接距離がle以下の場合はこれを修正
		for(int k=0;k<newN;k++)
		{
			int i=beforeN+k;					//対応する粒子番号
			int G_id=index[k];				//格納する格子番号
			double mindis=le;
			int J=k;						//最近接距離の相手粒子
			for(int II=G_id-1;II<=G_id+1;II++)
			{       
				for(int JJ=-1*grid_sizeX;JJ<=grid_sizeX;JJ+=grid_sizeX)
				{
					int M_id=II+JJ;
					for(int L=0;L<MESH[M_id].size();L++)
					{
						int j=MESH[M_id][L];
						double x=PART[j].Get_X()-PART[i].Get_X();
						double y=PART[j].Get_Y()-PART[i].Get_Y();
						double dis=sqrt(x*x+y*y);
						if(dis<mindis && i!=j)
						{
							mindis=dis;
							J=j;
						}
					}
				}
			}
			if(J!=i && J<beforeN)//leより近接している相手が境界粒子なら
			{
				double L=le-mindis;//開くべき距離
				double dX=PART[J].Get_X()-PART[i].Get_X();
				double dY=PART[J].Get_Y()-PART[i].Get_Y();
				PART[i].Add(-(dX/mindis*L), -(dY/mindis*L), 0);		
			}
			else if(J!=i && J>=beforeN)//leより近接している相手が内部粒子なら
			{
				double L=0.5*(le-mindis);//開くべき距離
				double dX=PART[J].Get_X()-PART[i].Get_X();
				double dY=PART[J].Get_Y()-PART[i].Get_Y();
				PART[i].Add(-(dX/mindis*L), -(dY/mindis*L), 0);	
				PART[J].Add(dX/mindis*L, dY/mindis*L, 0);	
			}
		}//////////*/
	}/////MD終了

	delete [] index;
//	delete [] MESH;
}