void FemPoroelasticResidualLocalAssembler::assembleComponents
    (   const NumLib::TimeStep &timestep,
        const MeshLib::IElement &e, 
        const std::vector<size_t> &vec_order, 
        const std::vector<LocalVectorType> &vec_x0,
        const std::vector<LocalVectorType> &vec_x1,
        std::vector<LocalVectorType> &vec_r
        )
{
    assert(vec_order.size()==3);

    //TODO how do you know 1st is ux and 3rd is p? who decides it?
    const size_t id_ux = 0;
    const size_t id_uy = 1;
    const size_t id_p = 2;

    const size_t u_order = vec_order[id_ux];
    assert(u_order==vec_order[id_uy]);
    const size_t p_order = vec_order[id_p];
    const LocalVectorType &ux0 = vec_x0[id_ux];
    const LocalVectorType &uy0 = vec_x0[id_uy];
    const LocalVectorType &ux1 = vec_x1[id_ux];
    const LocalVectorType &uy1 = vec_x1[id_uy];
    // combine ux and uy
    LocalVectorType u0(ux0.rows()*2);
    LocalVectorType u1(ux0.rows()*2);
    for (int i=0; i<ux0.rows(); i++) {
        u0(i) = ux0(i);
        u0(i+ux0.rows()) = uy0(i);
        u1(i) = ux1(i);
        u1(i+ux0.rows()) = uy1(i);
    }
    const LocalVectorType &p0 = vec_x0[id_p];
    const LocalVectorType &p1 = vec_x1[id_p];
    // ------------------------------------------------------------------------
    // Element
    // ------------------------------------------------------------------------
    const size_t dim = e.getDimension();
    const size_t n_strain_components = getNumberOfStrainComponents(dim);
    const size_t nnodes_u = e.getNumberOfNodes(u_order);
    const size_t nnodes_p = e.getNumberOfNodes(p_order);
    const NumLib::TXPosition e_pos(NumLib::TXPosition::Element, e.getID());

    // ------------------------------------------------------------------------
    // Transient
    // ------------------------------------------------------------------------
    const double dt = timestep.getTimeStepSize();
    const double theta = 1.0;

    // ------------------------------------------------------------------------
    // Material (assuming element constant)
    // ------------------------------------------------------------------------
    size_t mat_id = e.getGroupID();
    size_t fluid_id = 0; //TODO
    Ogs6FemData* femData = Ogs6FemData::getInstance();
    MaterialLib::PorousMedia* pm = femData->list_pm[mat_id];
    MaterialLib::Solid *solidphase = femData->list_solid[mat_id];
    MaterialLib::Fluid *fluidphase = femData->list_fluid[fluid_id];

    // solid
    double rho_s = .0;
    if (solidphase->density!=NULL)
        solidphase->density->eval(e_pos, rho_s);
    LocalMatrixType De = LocalMatrixType::Zero(n_strain_components, n_strain_components);
    MathLib::LocalMatrix nv(1,1);
    MathLib::LocalMatrix E(1,1);
    solidphase->poisson_ratio->eval(e_pos, nv);
    solidphase->Youngs_modulus->eval(e_pos, E);
    double Lambda, G, K;
    MaterialLib::calculateLameConstant(nv(0,0), E(0,0), Lambda, G, K);
    MaterialLib::setElasticConsitutiveTensor(dim, Lambda, G, De);

    // fluid
    double mu = .0;
    fluidphase->dynamic_viscosity->eval(e_pos, mu);
    double rho_f = .0;
    fluidphase->density->eval(e_pos, rho_f);

    // media
    double k;
    pm->permeability->eval(e_pos, k);
    double n = .0;
    pm->porosity->eval(e_pos, n);
    double s = .0;
    pm->storage->eval(e_pos, s);
    double k_mu;
    k_mu = k / mu;


    // ------------------------------------------------------------------------
    // Body force
    // ------------------------------------------------------------------------
    LocalVectorType body_force = LocalVectorType::Zero(dim);
    bool hasGravity = false;
    if (hasGravity) {
        body_force[dim-1] = rho_s * 9.81;
    }

    // ------------------------------------------------------------------------
    // Local component assembly
    // ------------------------------------------------------------------------
    LocalMatrixType Kuu = LocalMatrixType::Zero(nnodes_u*dim, nnodes_u*dim);
    LocalMatrixType Cup = LocalMatrixType::Zero(nnodes_u*dim, nnodes_p);
    LocalMatrixType Kpp = LocalMatrixType::Zero(nnodes_p, nnodes_p);
    LocalMatrixType Mpp = LocalMatrixType::Zero(nnodes_p, nnodes_p);
    LocalMatrixType Cpu = LocalMatrixType::Zero(nnodes_p, nnodes_u*dim);
    LocalVectorType Fu = LocalVectorType::Zero(nnodes_u*dim);
    LocalVectorType Fp = LocalVectorType::Zero(nnodes_p);

    // temp matrix
    LocalMatrixType B = LocalMatrixType::Zero(n_strain_components, nnodes_u*dim);
    LocalMatrixType Nuvw = LocalMatrixType::Zero(dim, nnodes_u*dim);
    const LocalMatrixType m = get_m(dim);

    //
    FemLib::IFiniteElement* fe_u = _feObjects.getFeObject(e, u_order);
    FemLib::IFiniteElement* fe_p = _feObjects.getFeObject(e, p_order);
    FemLib::IFemNumericalIntegration *q_u = fe_u->getIntegrationMethod();
    double gp_x[3], real_x[3];
    for (size_t j=0; j<q_u->getNumberOfSamplingPoints(); j++) {
        q_u->getSamplingPoint(j, gp_x);
        fe_u->computeBasisFunctions(gp_x);
        fe_p->computeBasisFunctions(gp_x);
        fe_u->getRealCoordinates(real_x);
        double fac_u = fe_u->getDetJ() * q_u->getWeight(j);

        //--- local component ----
        // set N,B
        LocalMatrixType &Nu = *fe_u->getBasisFunction();
        LocalMatrixType &dNu = *fe_u->getGradBasisFunction();
        setNu_Matrix_byComponent(dim, nnodes_u, Nu, Nuvw);
        setB_Matrix_byComponent(dim, nnodes_u, dNu, B);
        LocalMatrixType &Np = *fe_p->getBasisFunction();

        // K_uu += B^T * D * B
        Kuu.noalias() += fac_u * B.transpose() * De * B;

        // C_up += B^T * m * Np
        Cup.noalias() += fac_u * B.transpose() * m * Np;

        // Fu += N^T * b
        if (hasGravity) {
            Fu.noalias() += fac_u * Nuvw.transpose() * body_force;
        }
    }
    Fu.noalias() += (theta - 1) * Kuu * u0 + (1-theta)* Cup * p0;

    FemLib::IFemNumericalIntegration *q_p = fe_p->getIntegrationMethod();
    for (size_t j=0; j<q_p->getNumberOfSamplingPoints(); j++) {
        q_p->getSamplingPoint(j, gp_x);
        fe_u->computeBasisFunctions(gp_x);
        fe_p->computeBasisFunctions(gp_x);
        fe_p->getRealCoordinates(real_x);
        double fac = fe_p->getDetJ() * q_p->getWeight(j);

        //--- local component ----
        // set N,B
        LocalMatrixType &dNu = *fe_u->getGradBasisFunction();
        setB_Matrix_byComponent(dim, nnodes_u, dNu, B);
        LocalMatrixType &Np = *fe_p->getBasisFunction();
        LocalMatrixType &dNp = *fe_p->getGradBasisFunction();

        // M_pp += Np^T * S * Np
        Mpp.noalias() += fac * Np.transpose() * s * Np;

        // K_pp += dNp^T * K * dNp
        Kpp.noalias() += fac * dNp.transpose() * k_mu * dNp;

        // C_pu += Np^T * m^T * B
        Cpu.noalias() += fac * Np.transpose() * m.transpose() * B;
    }

    // Backward euler
    Fp = (1.0/dt * Mpp - (1-theta)*Kpp)* p0 + 1.0/dt * Cpu * u0;

    // r = K*u - RHS
    LocalVectorType r_u = Kuu * u1 - Cup * p1 - Fu;
    LocalVectorType r_p = 1.0/dt * Cpu * u1 + (1.0/dt * Mpp + theta * Kpp) * p1 - Fp;
//    if (e.getID()==0) {
//        std::cout << "u1=" << std::endl << u1 << std::endl;
//        std::cout << "p1=" << std::endl << p1 << std::endl;
//        std::cout << "Fp=" << std::endl << Fp << std::endl;
//        std::cout << "r_p=" << std::endl << r_p << std::endl;
//    }

    //
    for (size_t i=0; i<dim; i++) {
        vec_r[i] = r_u.segment(i*nnodes_u, nnodes_u);
    }
    vec_r[id_p] = r_p;
}
Example #2
0
int main(int argc, char **argv) {
	ASSERT(X_SIZE  > 0 &&
	       T_SIZE  > 0 &&
	       X_CELLS > 0 &&
	       T_CELLS > 0,   "Bad start parametres for the issue");
	ASSERT(argc == 2, "Input is a mode: 's' for stability or 'p' for perfomance");
	ASSERT(!strcmp(argv[1], "s") || !strcmp(argv[1], "p"), "Input is a mode: 's' for stability or 'p' for perfomance");
	ASSERT(lround(ux0(0)) == lround(ut0(0)), "Bad start data");

	int is_perf = 0; // stability - 0, perfomance - 1
	if (!strcmp(argv[1], "p"))
		is_perf = 1;

//	const double T_SIZE = 1 / TIME;
	const double DX = X_SIZE / X_CELLS;
	const double DT = T_SIZE / T_CELLS;

	int i = 0, j = 0;
	double temp = 0;
	double min_val = ux0(0), max_val = ux0(0);
	
	for (i = 0; i <= T_CELLS; i++) {
		temp = ux0(DT * i);
		if (temp < min_val) min_val = temp;
		if (temp > max_val) max_val = temp;
	}

	for (i = 0; i <= X_CELLS; i++) {
		temp = ut0(DX * i);
		if (temp < min_val) min_val = temp;
		if (temp > max_val) max_val = temp;
	}
	
	ASSERT(MPI_Init(&argc, &argv) >= 0, "Init. failure");	
	int core_num = 0, rank = 0;
	ASSERT(MPI_Comm_size(MPI_COMM_WORLD, &core_num) >= 0, "Size init. failure");
	ASSERT(core_num <= MAX_CORES && core_num > 0,         "Bad thread number" );
	ASSERT(MPI_Comm_rank(MPI_COMM_WORLD, &rank) >= 0,     "Rank init. failure");
	ASSERT(rank < core_num && rank >= 0,                  "Wrong thread rank.");
	ASSERT(rank != 0 || core_num <= X_CELLS,              "cores' number shouls be less than X_CELLS");

	int line_num = X_CELLS / core_num;
	int start_line = 1;
	j = X_CELLS % core_num;
	for (i = 0; i < rank; i++) {
		start_line += line_num;
		if (i < j) start_line++;
	}
	if (rank < j) line_num++;
	int end_line = start_line + line_num - 1;
	double **u = (double **) calloc(line_num + 1, sizeof(double *));
	for (i = 0; i <= line_num; i++)
		u[i] = (double *) calloc(T_CELLS + 1, sizeof(double));

	double time_val = MPI_Wtime();

	for (i = -1; i < line_num; i++)
		u[i + 1][0] = ut0(DX * (i + start_line));

	for (i = 1; i <= T_CELLS; i++) {
		if (rank >  0) {
			ASSERT(MPI_Recv((void *) &(u[0][i]), 1, MPI_DOUBLE, rank - 1, 0, MPI_COMM_WORLD, NULL) >= 0, "Failed to recieve.");
		} else {
			u[0][i] = ux0(DT * i);
		}

		for (j = 1; j <= line_num; j++) {
			u[j][i] = ( 2 * f((j - 1 + start_line - 0.5) * DX, (i - 0.5) * DT) - 
			                    (u[j][i - 1] - u[j - 1][i - 1] - u[j - 1][i]    ) / DT - 
			            SPEED * (u[j - 1][i] - u[j][i - 1]     - u[j - 1][i - 1]) / DX   ) * DT * DX / (SPEED * DT + DX);
		
			if (u[j][i] > max_val) max_val = u[j][i];
			if (u[j][i] < min_val) min_val = u[j][i];
		}
	
		if (end_line != X_CELLS)
			ASSERT(MPI_Send((void *) &(u[line_num][i]), 1, MPI_DOUBLE, rank + 1, 0, MPI_COMM_WORLD) >= 0, "Failed to recieve.");
	}

	time_val = MPI_Wtime() - time_val;
	


	double sup_buf[3] = {};
	if (rank != 0) {
		sup_buf[0] = min_val;
		sup_buf[1] = max_val;
		sup_buf[2] = time_val;
		ASSERT(MPI_Send((void *) sup_buf, 3, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD) >= 0, "Failed to send.");
	} else {
		for (i = 1; i < core_num; i++) {
			ASSERT(MPI_Recv((void *) sup_buf, 3, MPI_DOUBLE, i, 0, MPI_COMM_WORLD, NULL) >= 0, "Failed to recieve.");
			if (sup_buf[0] < min_val) min_val = sup_buf[0];
			if (sup_buf[1] > max_val) max_val = sup_buf[1];
			if (sup_buf[2] > time_val) time_val = sup_buf[2];
		}
	}

	if (rank != 0) {
		for (i = 1; i <= line_num; i++) 
			ASSERT(MPI_Send((void *) u[i], T_CELLS + 1, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD) >= 0, "Failed to send.");
	} else {
		double **u_buf = (double **) calloc(X_CELLS + 1, sizeof(double *));
		for (i = 0; i <= X_CELLS; i++)
			u_buf[i] = (double *) calloc(T_CELLS + 1, sizeof(double));
		for (i = 0; i <= line_num; i++) {
			for (j = 0; j <= T_CELLS; j++) {
				u_buf[i][j] = u[i][j];
			}
		}
		int line_counter = line_num + 1;
		for (i = 1; i < core_num; i++) {
			line_num = X_CELLS / core_num;
			if (i < X_CELLS % core_num) line_num++;
			for (j = 0; j < line_num; j++) {
				ASSERT(MPI_Recv((void *) u_buf[line_counter], T_CELLS + 1, MPI_DOUBLE, i, 0, MPI_COMM_WORLD, NULL) >= 0, "Failed to recieve.");
				line_counter++;
			}
		}
	
		print_all(u_buf, is_perf, min_val, max_val);

		for (i = 0; i <= X_CELLS; i++)
			free(u_buf[i]);
		free(u_buf);
	}
	
	for (i = 0; i <= line_num; i++) free(u[i]);
	free(u);

	if (rank == 0) printf("Time: %.2lf seconds\n", time_val);

	MPI_Finalize();
	return 0;
}