int main (int argc, char **argv) { GetPot cl (argc, argv); if (cl.search (2, "-h", "--help")) { std::cerr << help_text << std::endl; return 0; } const double a = cl.follow (0.0, "-a"); const double b = cl.follow (1.0, "-b"); const unsigned int nnodes = cl.follow (100, 2, "-n", "--nnodes"); const std::string diffusion = cl.follow ("1.0", 2, "-d", "--diffusion"); const std::string forcing = cl.follow ("1.0", 2, "-f", "--forcing"); std::unique_ptr<mesh<double>> m (new mesh<double> (a, b, nnodes)); fem_1d<double> problem (std::move (m)); coeff<double> a_coeff (diffusion); problem.set_diffusion_coefficient (a_coeff); coeff<double> f_coeff (forcing); problem.set_source_coefficient (f_coeff); problem.assemble (); problem.set_dirichlet (fem_1d<double>::left_boundary, 0.0); problem.set_dirichlet (fem_1d<double>::right_boundary, 0.0); problem.solve (); for (unsigned int ii = 0; ii < nnodes; ++ii) std::cout << problem.m->nodes[ii] << " " << problem.result ()(ii, 0) << std:: endl; return 0; };
ConstitutiveModelParameters<EvalT, Traits>:: ConstitutiveModelParameters(Teuchos::ParameterList& p, const Teuchos::RCP<Albany::Layouts>& dl) : have_temperature_(false), dl_(dl) { // get number of integration points and spatial dimensions std::vector<PHX::DataLayout::size_type> dims; dl_->qp_vector->dimensions(dims); num_pts_ = dims[1]; num_dims_ = dims[2]; // get the Parameter Library Teuchos::RCP<ParamLib> paramLib = p.get<Teuchos::RCP<ParamLib> >("Parameter Library", Teuchos::null); // get the material parameter list Teuchos::ParameterList* mat_params = p.get<Teuchos::ParameterList*>("Material Parameters"); // Check for optional field: temperature if (p.isType<std::string>("Temperature Name")) { have_temperature_ = true; PHX::MDField<ScalarT, Cell, QuadPoint> tmp(p.get<std::string>("Temperature Name"), dl_->qp_scalar); temperature_ = tmp; this->addDependentField(temperature_); } // step through the possible parameters, registering as necessary // // elastic modulus std::string e_mod("Elastic Modulus"); if (mat_params->isSublist(e_mod)) { PHX::MDField<ScalarT, Cell, QuadPoint> tmp(e_mod, dl_->qp_scalar); elastic_mod_ = tmp; field_map_.insert(std::make_pair(e_mod, elastic_mod_)); parseParameters(e_mod, p, paramLib); } // Poisson's ratio std::string pr("Poissons Ratio"); if (mat_params->isSublist(pr)) { PHX::MDField<ScalarT, Cell, QuadPoint> tmp(pr, dl_->qp_scalar); poissons_ratio_ = tmp; field_map_.insert(std::make_pair(pr, poissons_ratio_)); parseParameters(pr, p, paramLib); } // bulk modulus std::string b_mod("Bulk Modulus"); if (mat_params->isSublist(b_mod)) { PHX::MDField<ScalarT, Cell, QuadPoint> tmp(b_mod, dl_->qp_scalar); bulk_mod_ = tmp; field_map_.insert(std::make_pair(b_mod, bulk_mod_)); parseParameters(b_mod, p, paramLib); } // shear modulus std::string s_mod("Shear Modulus"); if (mat_params->isSublist(s_mod)) { PHX::MDField<ScalarT, Cell, QuadPoint> tmp(s_mod, dl_->qp_scalar); shear_mod_ = tmp; field_map_.insert(std::make_pair(s_mod, shear_mod_)); parseParameters(s_mod, p, paramLib); } // yield strength std::string yield("Yield Strength"); if (mat_params->isSublist(yield)) { PHX::MDField<ScalarT, Cell, QuadPoint> tmp(yield, dl_->qp_scalar); yield_strength_ = tmp; field_map_.insert(std::make_pair(yield, yield_strength_)); parseParameters(yield, p, paramLib); } // hardening modulus std::string h_mod("Hardening Modulus"); if (mat_params->isSublist(h_mod)) { PHX::MDField<ScalarT, Cell, QuadPoint> tmp(h_mod, dl_->qp_scalar); hardening_mod_ = tmp; field_map_.insert(std::make_pair(h_mod, hardening_mod_)); parseParameters(h_mod, p, paramLib); } // recovery modulus std::string r_mod("Recovery Modulus"); if (mat_params->isSublist(r_mod)) { PHX::MDField<ScalarT, Cell, QuadPoint> tmp(r_mod, dl_->qp_scalar); recovery_mod_ = tmp; field_map_.insert(std::make_pair(r_mod, recovery_mod_)); parseParameters(r_mod, p, paramLib); } // concentration equilibrium parameter std::string c_eq("Concentration Equilibrium Parameter"); if (mat_params->isSublist(c_eq)) { PHX::MDField<ScalarT, Cell, QuadPoint> tmp(c_eq, dl_->qp_scalar); conc_eq_param_ = tmp; field_map_.insert(std::make_pair(c_eq, conc_eq_param_)); parseParameters(c_eq, p, paramLib); } // diffusion coefficient std::string d_coeff("Diffusion Coefficient"); if (mat_params->isSublist(d_coeff)) { PHX::MDField<ScalarT, Cell, QuadPoint> tmp(d_coeff, dl_->qp_scalar); diff_coeff_ = tmp; field_map_.insert(std::make_pair(d_coeff, diff_coeff_)); parseParameters(d_coeff, p, paramLib); } // thermal conductivity std::string th_cond("Thermal Conductivity"); if (mat_params->isSublist(th_cond)) { PHX::MDField<ScalarT, Cell, QuadPoint> tmp(th_cond, dl_->qp_scalar); thermal_cond_ = tmp; field_map_.insert(std::make_pair(th_cond, thermal_cond_)); parseParameters(th_cond, p, paramLib); } // flow rule coefficient std::string f_coeff("Flow Rule Coefficient"); if (mat_params->isSublist(f_coeff)) { PHX::MDField<ScalarT, Cell, QuadPoint> tmp(f_coeff, dl_->qp_scalar); flow_coeff_ = tmp; field_map_.insert(std::make_pair(f_coeff, flow_coeff_)); parseParameters(f_coeff, p, paramLib); } // flow rule exponent std::string f_exp("Flow Rule Exponent"); if (mat_params->isSublist(f_exp)) { PHX::MDField<ScalarT, Cell, QuadPoint> tmp(f_exp, dl_->qp_scalar); flow_exp_ = tmp; field_map_.insert(std::make_pair(f_exp, flow_exp_)); parseParameters(f_exp, p, paramLib); } // register evaluated fields typename std::map<std::string, PHX::MDField<ScalarT, Cell, QuadPoint> >::iterator it; for (it = field_map_.begin(); it != field_map_.end(); ++it) { this->addEvaluatedField(it->second); } this->setName( "Constitutive Model Parameters" + PHX::TypeString<EvalT>::value); }
int main (int argc, char **argv) { GetPot cl (argc, argv); if (cl.search (2, "-h", "--help")) { std::cerr << help_text << std::endl; return 0; } const double a = cl.follow (double (0.0), "-a"); const double b = cl.follow (double (1.0), "-b"); const unsigned int nnodes = cl.follow (100, 2, "-n", "--nnodes"); const unsigned int nel = nnodes - 1; const std::string diffusion = cl.follow ("1.0", 2, "-d", "--diffusion"); const std::string forcing = cl.follow ("1.0", 2, "-f", "--forcing"); const double tol = 1e-6; const unsigned int maxit = 43; const unsigned int overlap = 3; const double L = b - a; const int mpi_size = 3; const double L_loc = L / double (mpi_size); const double h = L_loc / ceil (double(nel) / double(mpi_size)); std::vector<double> a_loc (mpi_size); std::vector<double> b_loc (mpi_size); std::vector<unsigned int> nel_loc (mpi_size); std::vector<unsigned int> ndof_loc (mpi_size); std::vector<fem_1d<double>*> subproblems (mpi_size); coeff<double> a_coeff (diffusion); coeff<double> f_coeff (forcing); int mpi_rank; for (mpi_rank = 0; mpi_rank < mpi_size; ++mpi_rank) { a_loc[mpi_rank] = a + mpi_rank * L_loc; b_loc[mpi_rank] = a_loc[mpi_rank] + L_loc; nel_loc[mpi_rank] = ceil (double(nel) / double(mpi_size)); if (mpi_rank > 0) { a_loc[mpi_rank] -= overlap * h; nel_loc[mpi_rank] += overlap; } if (mpi_rank < mpi_size - 1) { b_loc[mpi_rank] += overlap * h; nel_loc[mpi_rank] += overlap; } ndof_loc[mpi_rank] = nel_loc[mpi_rank] + 1; fem_1d<double>* tmp = new fem_1d<double>(new mesh<double> (a_loc[mpi_rank], b_loc[mpi_rank], ndof_loc[mpi_rank])); subproblems[mpi_rank] = tmp; subproblems[mpi_rank]->set_diffusion_coefficient (a_coeff); subproblems[mpi_rank]->set_source_coefficient (f_coeff); subproblems[mpi_rank]->assemble (); subproblems[mpi_rank]->set_dirichlet (fem_1d<double>::left_boundary, 0.0); subproblems[mpi_rank]->set_dirichlet (fem_1d<double>::right_boundary, 0.0); subproblems[mpi_rank]->solve (); }; for (unsigned int it = 0; it < maxit; ++it) for (mpi_rank = 0; mpi_rank < mpi_size; ++mpi_rank) { if (mpi_rank > 0) subproblems[mpi_rank]->set_dirichlet (fem_1d<double>::left_boundary, subproblems[mpi_rank-1]->result () [ndof_loc[mpi_rank-1]-1-2*overlap]); else subproblems[mpi_rank]->set_dirichlet (fem_1d<double>::left_boundary, 0.0); if (mpi_rank < mpi_size - 1) subproblems[mpi_rank]->set_dirichlet (fem_1d<double>::right_boundary, subproblems[mpi_rank+1]->result () [2*overlap]); else subproblems[mpi_rank]->set_dirichlet (fem_1d<double>::right_boundary, 0.0); subproblems[mpi_rank]->solve (); } for (mpi_rank = 0; mpi_rank < mpi_size; ++mpi_rank) for (unsigned int ii = 0; ii < ndof_loc[mpi_rank]; ++ii) std::cout << subproblems[mpi_rank]->m->nodes[ii] << " " << subproblems[mpi_rank]->result ()(ii, 0) << std::endl; return 0; };
int main (int argc, char **argv) { GetPot cl (argc, argv); if (cl.search (2, "-h", "--help")) { std::cerr << help_text << std::endl; return 0; } const double a = cl.follow (0.0, "-a"); const double b = cl.follow (1.0, "-b"); const unsigned int nnodes = cl.follow (100, 2, "-n", "--nnodes"); const std::string diffusion = cl.follow ("1.0", 2, "-d", "--diffusion"); const std::string forcing = cl.follow ("1.0", 2, "-f", "--forcing"); coeff f_coeff (forcing); coeff a_coeff (diffusion); const std::string quadrature = cl.follow ("trapezoidal.so", 2, "-q", "--quadrature-rule"); std::function <void ()> r_r; void * handle = dlopen (quadrature.c_str (), RTLD_NOW); if (! handle) { std::cerr << "fem1d: cannot load dynamic object!" << std::endl; std::cerr << dlerror () << std::endl; return (-1); } void * sym = dlsym (handle, "register_rules"); if (! sym) { std::cerr << "fem1d: cannot load symbol!" << std::endl; std::cerr << dlerror () << std::endl; return (-1); } r_r = reinterpret_cast <void (*) ()> (sym); r_r (); auto & the_factory = quadrature_factory::instance (); auto integrate = the_factory.create ("trapezoidal"); if (! integrate) { std::cerr << "rule name unknown" << std::endl; return (-1); } mesh m (a, b, nnodes); Eigen::SparseMatrix<double> A(nnodes, nnodes); Eigen::Matrix2d mloc; mloc << 0, 0, 0, 0; for (unsigned int iel = 0; iel < m.nels; ++iel) { mloc << 0, 0, 0, 0; for (unsigned int inode = 0; inode < 2; ++inode) { auto igrad = [=, &m] (double x) -> double { return basisfungrad (x, m.nodes[m.elements[iel][0]], m.nodes[m.elements[iel][1]], inode == 0 ? 1.0 : 0.0, inode == 1 ? 1.0 : 0.0); }; for (unsigned int jnode = 0; jnode < 2; ++jnode) { auto jgrad = [=, &m] (double x) -> double { return basisfungrad (x, m.nodes[m.elements[iel][0]], m.nodes[m.elements[iel][1]], jnode == 0 ? 1.0 : 0.0, jnode == 1 ? 1.0 : 0.0); }; mloc(inode,jnode) += (*integrate) ([=, &m, &igrad, &jgrad, &a_coeff] (double x) -> double { return (igrad (x) * jgrad (x) * a_coeff (x)); }, m.nodes[m.elements[iel][0]], m.nodes[m.elements[iel][1]]); A.coeffRef(m.elements[iel][inode], m.elements[iel][jnode]) += mloc(inode,jnode); } } } Eigen::VectorXd f(nnodes); for (unsigned int ii = 0; ii < nnodes; ++ii) f(ii) = 0.0; Eigen::Vector2d vloc; for (unsigned int iel = 0; iel < m.nels; ++iel) { vloc << 0, 0; for (unsigned int inode = 0; inode < 2; ++inode) { auto ifun = [=, &m] (double x) -> double { return basisfun (x, m.nodes[m.elements[iel][0]], m.nodes[m.elements[iel][1]], inode == 0 ? 1.0 : 0.0, inode == 1 ? 1.0 : 0.0); }; vloc(inode) += (*integrate) ([=, &m, &ifun, &f_coeff] (double x) -> double { return (ifun (x) * f_coeff (x)); }, m.nodes[m.elements[iel][0]], m.nodes[m.elements[iel][1]]); f(m.elements[iel][inode]) += vloc(inode); } } f(0) = 0; f(nnodes - 1) = 0; A.coeffRef(0,0) = 1.0e10; A.coeffRef(nnodes-1,nnodes-1) = 1.0e10; for (unsigned int ii = 1; ii < nnodes; ++ii) { A.coeffRef(0, ii) = 0.0; A.coeffRef(nnodes-1, nnodes-1-ii) = 0.0; } Eigen::SparseLU<Eigen::SparseMatrix<double>> solver; A.makeCompressed (); solver.analyzePattern(A); solver.factorize(A); Eigen::VectorXd uh = solver.solve (f); for (unsigned int ii = 0; ii < nnodes; ++ii) std::cout << m.nodes[ii] << " " << uh(ii, 0) << std:: endl; return 0; };
int main (int argc, char **argv) { MPI_Init (&argc, &argv); GetPot cl (argc, argv); if (cl.search (2, "-h", "--help")) { std::cerr << help_text << std::endl; return 0; } const double a = cl.follow (double (0.0), "-a"); const double b = cl.follow (double (1.0), "-b"); const unsigned int nnodes = cl.follow (100, 2, "-n", "--nnodes"); const unsigned int nel = nnodes - 1; const std::string diffusion = cl.follow ("1.0", 2, "-d", "--diffusion"); const std::string forcing = cl.follow ("1.0", 2, "-f", "--forcing"); const double L = b - a; constexpr double tol = 1e-6; constexpr unsigned int maxit = 100; constexpr unsigned int overlap = 100; MPI_Status status; int mpi_size, mpi_rank, tag; MPI_Comm_size (MPI_COMM_WORLD, &mpi_size); MPI_Comm_rank (MPI_COMM_WORLD, &mpi_rank); const double L_loc = L / double(mpi_size); const double h = L_loc / ceil (double(nel) / double(mpi_size)); double a_loc = .0; double lval = .0; double b_loc = .0; double rval = .0; double buffer = .0; unsigned int nel_loc = 0; unsigned int ndof_loc = 1; fem_1d<double> *subproblems; coeff<double> a_coeff (diffusion); coeff<double> f_coeff (forcing); a_loc = a + mpi_rank * L_loc; b_loc = a_loc + L_loc; nel_loc = ceil (double(nel) / double(mpi_size)); if (mpi_rank > 0) { a_loc -= overlap * h; nel_loc += overlap; } if (mpi_rank < mpi_size - 1) { b_loc += overlap * h; nel_loc += overlap; } ndof_loc = nel_loc + 1; subproblems = new fem_1d<double> (new mesh<double> (a_loc, b_loc, ndof_loc)); subproblems->set_diffusion_coefficient (a_coeff); subproblems->set_source_coefficient (f_coeff); subproblems->assemble (); subproblems->set_dirichlet (fem_1d<double>::left_boundary, 0.0); subproblems->set_dirichlet (fem_1d<double>::right_boundary, 0.0); subproblems->solve (); for (unsigned int it = 0; it < maxit; ++it) { // With the following implementation // communication will occur sequentailly // left to right first then right to left // Receive from left neighbour if (mpi_rank > 0) { std::cerr << "rank " << mpi_rank << " receiving lval from rank " << mpi_rank - 1 << std::endl; MPI_Recv (&buffer, 1, MPI_DOUBLE, mpi_rank - 1, MPI_ANY_TAG, MPI_COMM_WORLD, &status); std::cerr << "rank " << mpi_rank << " received lval from rank " << mpi_rank - 1 << std::endl; lval = buffer; } tag = 10*mpi_rank; // Send to right neighbour if (mpi_rank < mpi_size - 1) { buffer = subproblems->result () [ndof_loc - 1 - 2*overlap]; std::cerr << "rank " << mpi_rank << " sending lval to rank " << mpi_rank + 1 << std::endl; MPI_Send (&buffer, 1, MPI_DOUBLE, mpi_rank + 1, tag, MPI_COMM_WORLD); std::cerr << "rank " << mpi_rank << " sent lval to rank " << mpi_rank + 1 << std::endl; } // Receive from right neighbour if (mpi_rank < mpi_size - 1) { std::cerr << "rank " << mpi_rank << " receiving rval from rank " << mpi_rank + 1 << std::endl; MPI_Recv (&buffer, 1, MPI_DOUBLE, mpi_rank + 1, MPI_ANY_TAG, MPI_COMM_WORLD, &status); std::cerr << "rank " << mpi_rank << " received rval from rank " << mpi_rank + 1 << std::endl; rval = buffer; } tag = 10*mpi_rank + 1; // Send to right neighbour if (mpi_rank > 0) { buffer = subproblems->result () [2*overlap]; std::cerr << "rank " << mpi_rank << " sending rval to rank " << mpi_rank - 1 << std::endl; MPI_Send (&buffer, 1, MPI_DOUBLE, mpi_rank - 1, tag, MPI_COMM_WORLD); std::cerr << "rank " << mpi_rank << " sent rval to rank " << mpi_rank - 1 << std::endl; } subproblems->set_dirichlet (fem_1d<double>::left_boundary, lval); subproblems->set_dirichlet (fem_1d<double>::right_boundary, rval); subproblems->solve (); } for (int rank = 0; rank < mpi_size; ++rank) { if (rank == mpi_rank) for (unsigned int ii = 0; ii < ndof_loc; ++ii) std::cout << subproblems->m->nodes[ii] << " " << subproblems->result ()(ii, 0) << std::endl; MPI_Barrier (MPI_COMM_WORLD); } MPI_Finalize (); return 0; };