void FemPoroelasticResidualLocalAssembler::assembleComponents ( const NumLib::TimeStep ×tep, 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; }
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; }