bool KinematicsSolver::getBestSolution(ColumnVector& cartesian, ColumnVector& currentQ, ColumnVector& bestSolution) { if (this->solve(cartesian, currentQ)) { SolutionSet* set = selector->getBest(); ColumnVector soln(6); for (int i = 0; i < 6; i++) { soln(i + 1) = set->theta[i]; } bestSolution = soln; return true; } return false; }
/** * Create query solution. */ QuerySolution* createQuerySolution() { std::auto_ptr<QuerySolution> soln(new QuerySolution()); soln->cacheData.reset(new SolutionCacheData()); soln->cacheData->solnType = SolutionCacheData::COLLSCAN_SOLN; soln->cacheData->tree.reset(new PlanCacheIndexTree()); return soln.release(); }
void CircuitState::zero() { uint i; for(i=0; i < cir->stateLen; i++) soln(i) = 0; time = 0; }
bool RichardsMultiphaseProblem::updateSolution(NumericVector<Number>& vec_solution, NumericVector<Number>& ghosted_solution) { bool updatedSolution = false; // this gets set to true if we needed to enforce the bound at any node unsigned int sys_num = getNonlinearSystem().number(); // For parallel procs i believe that i have to use local_nodes_begin, rather than just nodes_begin // _mesh comes from SystemBase (_mesh = getNonlinearSystem().subproblem().mesh(), and subproblem is this object) MeshBase::node_iterator nit = _mesh.getMesh().local_nodes_begin(); const MeshBase::node_iterator nend = _mesh.getMesh().local_nodes_end(); for ( ; nit != nend; ++nit) { const Node & node = *(*nit); // dofs[0] is the dof number of the bounded variable at this node // dofs[1] is the dof number of the lower variable at this node std::vector<unsigned int> dofs(2); dofs[0] = node.dof_number(sys_num, _bounded_var_num, 0); dofs[1] = node.dof_number(sys_num, _lower_var_num, 0); // soln[0] is the value of the bounded variable at this node // soln[1] is the value of the lower variable at this node std::vector<Number> soln(2); vec_solution.get(dofs, soln); // do the bounding if (soln[0] < soln[1]) { /* dof_id_type nd = node.id(); Moose::out << "nd = " << nd << " dof_bounded = " << dofs[0] << " dof_lower = " << dofs[1] << "\n"; Moose::out << " bounded_value = " << soln[0] << " lower_value = " << soln[1] << "\n"; */ vec_solution.set(dofs[0], soln[1]); // set the bounded variable equal to the lower value updatedSolution = true; } } // The above vec_solution.set calls potentially added "set" commands to a queue // The following actions the queue (doing MPI commands if necessary), so // vec_solution will actually be modified by this following command vec_solution.close(); // if any proc updated the solution, all procs will know about it _communicator.max(updatedSolution); if (updatedSolution) { ghosted_solution = vec_solution; ghosted_solution.close(); } return updatedSolution; }
//========================================================================================================================== // Test to verify the evaluate method with a vector input. //========================================================================================================================== int EvaluateVectorTest() { TestUtil testFramework( "PolyFit", "Evaluate", __FILE__, __LINE__ ); std::string failMesg; int n = 4; gpstk::PolyFit<double> test(n); gpstk::Vector<double> soln(3,0.), eval(3,0.); double indep[6] = {0, 1, 2, 3, 4, 5}, dep[6] = {0, 1, 4, 9, 16, 25}; eval[0] = 6; eval[1] = 8; eval[2] = 10; for(int i=0; i<6; i++) { test.Add(dep[i],indep[i]); } soln = test.Evaluate(eval); //std::cout << "Solution is: " << soln << std::endl; n = 0; for (int i = 0; i<3; i++) { // Using relative error since the soln >> 1 if (fabs(soln[i] - eval[i]*eval[i])/(eval[i]*eval[i]) > eps) { n += 1; // Increment the return value for each wrong value } } failMesg = "Was the solution computed correct?"; testFramework.assert(n==0, failMesg, __LINE__); return testFramework.countFails(); // Return the result of the test. }
QuerySolution* makeCollectionScan(const CanonicalQuery& query, bool tailable) { auto_ptr<QuerySolution> soln(new QuerySolution()); soln->filter.reset(query.root()->shallowClone()); // BSONValue, where are you? soln->filterData = query.getQueryObj(); // Make the (only) node, a collection scan. CollectionScanNode* csn = new CollectionScanNode(); csn->name = query.ns(); csn->filter = soln->filter.get(); csn->tailable = tailable; const BSONObj& sortObj = query.getParsed().getSort(); // TODO: We need better checking for this. Should be done in CanonicalQuery and we should // be able to assume it's correct. if (!sortObj.isEmpty()) { BSONElement natural = sortObj.getFieldDotted("$natural"); csn->direction = natural.numberInt() >= 0 ? 1 : -1; } // Add this solution to the list of solutions. soln->root.reset(csn); return soln.release(); }
// static QuerySolution* QueryPlannerAnalysis::analyzeDataAccess(const CanonicalQuery& query, const QueryPlannerParams& params, QuerySolutionNode* solnRoot) { auto_ptr<QuerySolution> soln(new QuerySolution()); soln->filterData = query.getQueryObj(); verify(soln->filterData.isOwned()); soln->ns = query.ns(); soln->indexFilterApplied = params.indexFiltersApplied; solnRoot->computeProperties(); // solnRoot finds all our results. Let's see what transformations we must perform to the // data. // If we're answering a query on a sharded system, we need to drop documents that aren't // logically part of our shard (XXX GREG elaborate more precisely) if (params.options & QueryPlannerParams::INCLUDE_SHARD_FILTER) { // XXX TODO: use params.shardKey to do fetch analysis instead of always fetching. if (!solnRoot->fetched()) { FetchNode* fetch = new FetchNode(); fetch->children.push_back(solnRoot); solnRoot = fetch; } ShardingFilterNode* sfn = new ShardingFilterNode(); sfn->children.push_back(solnRoot); solnRoot = sfn; } solnRoot = analyzeSort(query, params, solnRoot, &soln->hasSortStage); // This can happen if we need to create a blocking sort stage and we're not allowed to. if (NULL == solnRoot) { return NULL; } // If we can (and should), add the keep mutations stage. // We cannot keep mutated documents if: // // 1. The query requires an index to evaluate the predicate ($text). We can't tell whether // or not the doc actually satisfies the $text predicate since we can't evaluate a // text MatchExpression. // // 2. The query implies a sort ($geoNear). It would be rather expensive and hacky to merge // the document at the right place. // // 3. There is an index-provided sort. Ditto above comment about merging. // XXX; do we want some kind of static init for a set of stages we care about & pass that // set into hasNode? bool cannotKeepFlagged = hasNode(solnRoot, STAGE_TEXT) || hasNode(solnRoot, STAGE_GEO_NEAR_2D) || hasNode(solnRoot, STAGE_GEO_NEAR_2DSPHERE) || (!query.getParsed().getSort().isEmpty() && !soln->hasSortStage); // Only these stages can produce flagged results. A stage has to hold state past one call // to work(...) in order to possibly flag a result. bool couldProduceFlagged = hasNode(solnRoot, STAGE_GEO_2D) || hasNode(solnRoot, STAGE_AND_HASH) || hasNode(solnRoot, STAGE_AND_SORTED) || hasNode(solnRoot, STAGE_FETCH); bool shouldAddMutation = !cannotKeepFlagged && couldProduceFlagged; if (shouldAddMutation && (params.options & QueryPlannerParams::KEEP_MUTATIONS)) { KeepMutationsNode* keep = new KeepMutationsNode(); // We must run the entire expression tree to make sure the document is still valid. keep->filter.reset(query.root()->shallowClone()); if (STAGE_SORT == solnRoot->getType()) { // We want to insert the invalidated results before the sort stage, if there is one. verify(1 == solnRoot->children.size()); keep->children.push_back(solnRoot->children[0]); solnRoot->children[0] = keep; } else { keep->children.push_back(solnRoot); solnRoot = keep; } } // Project the results. if (NULL != query.getProj()) { QLOG() << "PROJECTION: fetched status: " << solnRoot->fetched() << endl; QLOG() << "PROJECTION: Current plan is:\n" << solnRoot->toString() << endl; if (query.getProj()->requiresDocument()) { QLOG() << "PROJECTION: claims to require doc adding fetch.\n"; // If the projection requires the entire document, somebody must fetch. if (!solnRoot->fetched()) { FetchNode* fetch = new FetchNode(); fetch->children.push_back(solnRoot); solnRoot = fetch; } } else { QLOG() << "PROJECTION: requires fields\n"; const vector<string>& fields = query.getProj()->getRequiredFields(); bool covered = true; for (size_t i = 0; i < fields.size(); ++i) { if (!solnRoot->hasField(fields[i])) { QLOG() << "PROJECTION: not covered cuz doesn't have field " << fields[i] << endl; covered = false; break; } } QLOG() << "PROJECTION: is covered?: = " << covered << endl; // If any field is missing from the list of fields the projection wants, // a fetch is required. if (!covered) { FetchNode* fetch = new FetchNode(); fetch->children.push_back(solnRoot); solnRoot = fetch; } } // We now know we have whatever data is required for the projection. ProjectionNode* projNode = new ProjectionNode(); projNode->children.push_back(solnRoot); projNode->fullExpression = query.root(); projNode->projection = query.getParsed().getProj(); solnRoot = projNode; } else { // If there's no projection, we must fetch, as the user wants the entire doc. if (!solnRoot->fetched()) { FetchNode* fetch = new FetchNode(); fetch->children.push_back(solnRoot); solnRoot = fetch; } } if (0 != query.getParsed().getSkip()) { SkipNode* skip = new SkipNode(); skip->skip = query.getParsed().getSkip(); skip->children.push_back(solnRoot); solnRoot = skip; } // When there is both a blocking sort and a limit, the limit will // be enforced by the blocking sort. // Otherwise, we need to limit the results in the case of a hard limit // (ie. limit in raw query is negative) if (0 != query.getParsed().getNumToReturn() && !soln->hasSortStage && !query.getParsed().wantMore()) { LimitNode* limit = new LimitNode(); limit->limit = query.getParsed().getNumToReturn(); limit->children.push_back(solnRoot); solnRoot = limit; } soln->root.reset(solnRoot); return soln.release(); }
int main(int argc, char *argv[]) { Teuchos::GlobalMPISession mpiSession(&argc, &argv); // This little trick lets us print to std::cout only if a (dummy) command-line argument is provided. int iprint = argc - 1; Teuchos::RCP<std::ostream> outStream; Teuchos::oblackholestream bhs; // outputs nothing if (iprint > 0) outStream = Teuchos::rcp(&std::cout, false); else outStream = Teuchos::rcp(&bhs, false); int errorFlag = 0; // *** Example body. try { std::string filename = "input.xml"; Teuchos::RCP<Teuchos::ParameterList> parlist = Teuchos::rcp( new Teuchos::ParameterList() ); Teuchos::updateParametersFromXmlFile( filename, parlist.ptr() ); RealT V_th = parlist->get("Thermal Voltage", 0.02585); RealT lo_Vsrc = parlist->get("Source Voltage Lower Bound", 0.0); RealT up_Vsrc = parlist->get("Source Voltage Upper Bound", 1.0); RealT step_Vsrc = parlist->get("Source Voltage Step", 1.e-2); RealT true_Is = parlist->get("True Saturation Current", 1.e-12); RealT true_Rs = parlist->get("True Saturation Resistance", 0.25); RealT init_Is = parlist->get("Initial Saturation Current", 1.e-12); RealT init_Rs = parlist->get("Initial Saturation Resistance", 0.25); RealT lo_Is = parlist->get("Saturation Current Lower Bound", 1.e-16); RealT up_Is = parlist->get("Saturation Current Upper Bound", 1.e-1); RealT lo_Rs = parlist->get("Saturation Resistance Lower Bound", 1.e-2); RealT up_Rs = parlist->get("Saturation Resistance Upper Bound", 30.0); // bool use_lambertw = parlist->get("Use Analytical Solution",true); bool use_scale = parlist->get("Use Scaling For Epsilon-Active Sets",true); bool use_sqp = parlist->get("Use SQP", true); // bool use_linesearch = parlist->get("Use Line Search", true); // bool datatype = parlist->get("Get Data From Input File",false); // bool use_adjoint = parlist->get("Use Adjoint Gradient Computation",false); // int use_hessvec = parlist->get("Use Hessian-Vector Implementation",1); // 0 - FD, 1 - exact, 2 - GN // bool plot = parlist->get("Generate Plot Data",false); // RealT noise = parlist->get("Measurement Noise",0.0); EqualityConstraint_DiodeCircuit<RealT> con(V_th,lo_Vsrc,up_Vsrc,step_Vsrc); RealT alpha = 1.e-4; // regularization parameter (unused) int ns = 101; // number of Vsrc components int nz = 2; // number of optimization variables Objective_DiodeCircuit<RealT> obj(alpha,ns,nz); // Initialize iteration vectors. Teuchos::RCP<std::vector<RealT> > z_rcp = Teuchos::rcp( new std::vector<RealT> (nz, 0.0) ); Teuchos::RCP<std::vector<RealT> > yz_rcp = Teuchos::rcp( new std::vector<RealT> (nz, 0.0) ); Teuchos::RCP<std::vector<RealT> > soln_rcp = Teuchos::rcp( new std::vector<RealT> (nz, 0.0) ); (*z_rcp)[0] = init_Is; (*z_rcp)[1] = init_Rs; (*yz_rcp)[0] = init_Is; (*yz_rcp)[1] = init_Rs; (*soln_rcp)[0] = true_Is; (*soln_rcp)[1] = true_Rs; ROL::StdVector<RealT> z(z_rcp); ROL::StdVector<RealT> yz(yz_rcp); ROL::StdVector<RealT> soln(soln_rcp); Teuchos::RCP<ROL::Vector<RealT> > zp = Teuchos::rcp(&z,false); Teuchos::RCP<ROL::Vector<RealT> > yzp = Teuchos::rcp(&yz,false); Teuchos::RCP<std::vector<RealT> > u_rcp = Teuchos::rcp( new std::vector<RealT> (ns, 0.0) ); Teuchos::RCP<std::vector<RealT> > yu_rcp = Teuchos::rcp( new std::vector<RealT> (ns, 0.0) ); std::ifstream input_file("measurements.dat"); RealT temp, temp_scale; for (int i=0; i<ns; i++) { input_file >> temp; input_file >> temp; temp_scale = pow(10,int(log10(temp))); (*u_rcp)[i] = temp_scale*(RealT)rand()/(RealT)RAND_MAX; (*yu_rcp)[i] = temp_scale*(RealT)rand()/(RealT)RAND_MAX; } input_file.close(); ROL::StdVector<RealT> u(u_rcp); ROL::StdVector<RealT> yu(yu_rcp); Teuchos::RCP<ROL::Vector<RealT> > up = Teuchos::rcp(&u,false); Teuchos::RCP<ROL::Vector<RealT> > yup = Teuchos::rcp(&yu,false); Teuchos::RCP<std::vector<RealT> > jv_rcp = Teuchos::rcp( new std::vector<RealT> (ns, 1.0) ); ROL::StdVector<RealT> jv(jv_rcp); Teuchos::RCP<ROL::Vector<RealT> > jvp = Teuchos::rcp(&jv,false); ROL::Vector_SimOpt<RealT> x(up,zp); ROL::Vector_SimOpt<RealT> y(yup,yzp); // Check derivatives obj.checkGradient(x,x,y,true,*outStream); obj.checkHessVec(x,x,y,true,*outStream); con.checkApplyJacobian(x,y,jv,true,*outStream); con.checkApplyAdjointJacobian(x,yu,jv,x,true,*outStream); con.checkApplyAdjointHessian(x,yu,y,x,true,*outStream); // Check consistency of Jacobians and adjoint Jacobians. con.checkAdjointConsistencyJacobian_1(jv,yu,u,z,true,*outStream); con.checkAdjointConsistencyJacobian_2(jv,yz,u,z,true,*outStream); // Check consistency of solves. con.checkSolve(u,z,jv,true,*outStream); con.checkInverseJacobian_1(jv,yu,u,z,true,*outStream); con.checkInverseAdjointJacobian_1(yu,jv,u,z,true,*outStream); // Initialize reduced objective function. Teuchos::RCP<std::vector<RealT> > p_rcp = Teuchos::rcp( new std::vector<RealT> (ns, 0.0) ); ROL::StdVector<RealT> p(p_rcp); Teuchos::RCP<ROL::Vector<RealT> > pp = Teuchos::rcp(&p,false); Teuchos::RCP<ROL::Objective_SimOpt<RealT> > pobj = Teuchos::rcp(&obj,false); Teuchos::RCP<ROL::EqualityConstraint_SimOpt<RealT> > pcon = Teuchos::rcp(&con,false); ROL::Reduced_Objective_SimOpt<RealT> robj(pobj,pcon,up,pp); // Check derivatives. *outStream << "Derivatives of reduced objective" << std::endl; robj.checkGradient(z,z,yz,true,*outStream); robj.checkHessVec(z,z,yz,true,*outStream); // Bound constraints RealT tol = 1.e-12; Teuchos::RCP<std::vector<RealT> > g0_rcp = Teuchos::rcp( new std::vector<RealT> (nz, 0.0) );; ROL::StdVector<RealT> g0p(g0_rcp); robj.gradient(g0p,z,tol); *outStream << std::scientific << "Initial gradient = " << (*g0_rcp)[0] << " " << (*g0_rcp)[1] << "\n"; *outStream << std::scientific << "Norm of Gradient = " << g0p.norm() << "\n"; // Define scaling for epsilon-active sets (used in inequality constraints) RealT scale; if(use_scale){ scale = 1.0e-2/g0p.norm();} else{ scale = 1.0;} *outStream << std::scientific << "Scaling: " << scale << "\n"; /// Define constraints on Is and Rs BoundConstraint_DiodeCircuit<RealT> bcon(scale,lo_Is,up_Is,lo_Rs,up_Rs); //bcon.deactivate(); // Optimization *outStream << "\n Initial guess " << (*z_rcp)[0] << " " << (*z_rcp)[1] << std::endl; if (!use_sqp){ // Trust Region ROL::Algorithm<RealT> algo_tr("Trust Region",*parlist); std::clock_t timer_tr = std::clock(); algo_tr.run(z,robj,bcon,true,*outStream); *outStream << "\n Solution " << (*z_rcp)[0] << " " << (*z_rcp)[1] << "\n" << std::endl; *outStream << "Trust-Region required " << (std::clock()-timer_tr)/(RealT)CLOCKS_PER_SEC << " seconds.\n"; } else{ // SQP. //Teuchos::RCP<std::vector<RealT> > gz_rcp = Teuchos::rcp( new std::vector<RealT> (nz, 0.0) ); //ROL::StdVector<RealT> gz(gz_rcp); //Teuchos::RCP<ROL::Vector<RealT> > gzp = Teuchos::rcp(&gz,false); Teuchos::RCP<std::vector<RealT> > gu_rcp = Teuchos::rcp( new std::vector<RealT> (ns, 0.0) ); ROL::StdVector<RealT> gu(gu_rcp); Teuchos::RCP<ROL::Vector<RealT> > gup = Teuchos::rcp(&gu,false); //ROL::Vector_SimOpt<RealT> g(gup,gzp); ROL::Vector_SimOpt<RealT> g(gup,zp); Teuchos::RCP<std::vector<RealT> > c_rcp = Teuchos::rcp( new std::vector<RealT> (ns, 0.0) ); Teuchos::RCP<std::vector<RealT> > l_rcp = Teuchos::rcp( new std::vector<RealT> (ns, 0.0) ); ROL::StdVector<RealT> c(c_rcp); ROL::StdVector<RealT> l(l_rcp); ROL::Algorithm<RealT> algo_cs("Composite Step",*parlist); //x.zero(); std::clock_t timer_cs = std::clock(); algo_cs.run(x,g,l,c,obj,con,true,*outStream); *outStream << "\n Solution " << (*z_rcp)[0] << " " << (*z_rcp)[1] << "\n" << std::endl; *outStream << "Composite Step required " << (std::clock()-timer_cs)/(RealT)CLOCKS_PER_SEC << " seconds.\n"; } soln.axpy(-1.0, z); *outStream << "Norm of error: " << soln.norm() << std::endl; if (soln.norm() > 1e4*ROL::ROL_EPSILON) { errorFlag = 1; } } catch (std::logic_error err) { *outStream << err.what() << "\n"; errorFlag = -1000; }; // end try if (errorFlag != 0) std::cout << "End Result: TEST FAILED\n"; else std::cout << "End Result: TEST PASSED\n"; return 0; }
int verify_solution(const simple_mesh_description<typename VectorType::GlobalOrdinalType>& mesh, const VectorType& x, double tolerance, bool verify_whole_domain = false) { typedef typename VectorType::GlobalOrdinalType GlobalOrdinal; typedef typename VectorType::ScalarType Scalar; int global_nodes_x = mesh.global_box[0][1]+1; int global_nodes_y = mesh.global_box[1][1]+1; int global_nodes_z = mesh.global_box[2][1]+1; Box box; copy_box(mesh.local_box, box); //num-owned-nodes in each dimension is num-elems+1 //only if num-elems > 0 in that dimension *and* //we are at the high end of the global range in that dimension: if (box[0][1] > box[0][0] && box[0][1] == mesh.global_box[0][1]) ++box[0][1]; if (box[1][1] > box[1][0] && box[1][1] == mesh.global_box[1][1]) ++box[1][1]; if (box[2][1] > box[2][0] && box[2][1] == mesh.global_box[2][1]) ++box[2][1]; std::vector<GlobalOrdinal> rows; std::vector<Scalar> row_coords; int roffset = 0; for(int iz=box[2][0]; iz<box[2][1]; ++iz) { for(int iy=box[1][0]; iy<box[1][1]; ++iy) { for(int ix=box[0][0]; ix<box[0][1]; ++ix) { GlobalOrdinal row_id = get_id<GlobalOrdinal>(global_nodes_x, global_nodes_y, global_nodes_z, ix, iy, iz); Scalar x, y, z; get_coords(row_id, global_nodes_x, global_nodes_y, global_nodes_z, x, y, z); bool verify_this_point = false; if (verify_whole_domain) verify_this_point = true; else if (std::abs(x - 0.5) < 0.05 && std::abs(y - 0.5) < 0.05 && std::abs(z - 0.5) < 0.05) { verify_this_point = true; } if (verify_this_point) { rows.push_back(roffset); row_coords.push_back(x); row_coords.push_back(y); row_coords.push_back(z); } ++roffset; } } } int return_code = 0; const int num_terms = 300; err_info<Scalar> max_error; max_error.err = 0.0; for(size_t i=0; i<rows.size(); ++i) { Scalar computed_soln = x.coefs[rows[i]]; Scalar x = row_coords[i*3]; Scalar y = row_coords[i*3+1]; Scalar z = row_coords[i*3+2]; Scalar analytic_soln = 0.0; //set exact boundary-conditions: if (x == 1.0) { //x==1 is first, we want soln to be 1 even around the edges //of the x==1 plane where y and/or z may be 0 or 1... analytic_soln = 1; } else if (x == 0.0 || y == 0.0 || z == 0.0) { analytic_soln = 0; } else if (y == 1.0 || z == 1.0) { analytic_soln = 0; } else { analytic_soln = soln(x, y, z, num_terms, num_terms); } #ifdef MINIFE_DEBUG_VERBOSE std::cout<<"("<<x<<","<<y<<","<<z<<") row "<<rows[i]<<": computed: "<<computed_soln<<", analytic: "<<analytic_soln<<std::endl; #endif Scalar err = std::abs(analytic_soln - computed_soln); if (err > max_error.err) { max_error.err = err; max_error.computed = computed_soln; max_error.analytic = analytic_soln; max_error.coords[0] = x; max_error.coords[1] = y; max_error.coords[2] = z; } } Scalar local_max_err = max_error.err; Scalar global_max_err = 0; #ifdef HAVE_MPI MPI_Allreduce(&local_max_err, &global_max_err, 1, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD); #else global_max_err = local_max_err; #endif if (local_max_err == global_max_err) { if (max_error.err > tolerance) { std::cout << "max absolute error is "<<max_error.err<<":"<<std::endl; std::cout << " at position ("<<max_error.coords[0]<<","<<max_error.coords[1]<<","<<max_error.coords[2]<<"), "<<std::endl; std::cout << " computed solution: "<<max_error.computed<<", analytic solution: "<<max_error.analytic<<std::endl; } else { std::cout << "solution matches analytic solution to within "<<tolerance<<" or better."<<std::endl; } } if (global_max_err > tolerance) { return_code = 1; } return return_code; }
int main(int argc, char* argv[]) { BoxLib::Initialize(argc,argv); BL_PROFILE_VAR("main()", pmain); std::cout << std::setprecision(15); solver_type = BoxLib_C; bc_type = Periodic; Real a = 0.0; Real b = 1.0; // ---- First use the number of processors to decide how many grids you have. // ---- We arbitrarily decide to have one grid per MPI process in a uniform // ---- cubic domain, so we require that the number of processors be N^3. // ---- This requirement is somewhat arbitrary, but convenient for now. int nprocs = ParallelDescriptor::NProcs(); // N is the cube root of the number of processors int N(0); for(int i(1); i*i*i <= nprocs; ++i) { if(i*i*i == nprocs) { N = i; } } if(N == 0) { // not a cube if(ParallelDescriptor::IOProcessor()) { std::cerr << "**** Error: nprocs = " << nprocs << " is not currently supported." << std::endl; } BoxLib::Error("We require that the number of processors be a perfect cube"); } if(ParallelDescriptor::IOProcessor()) { std::cout << "N = " << N << std::endl; } // ---- make a box, then a boxarray with maxSize int domain_hi = (N*maxGrid) - 1; Box domain(IntVect(0,0,0), IntVect(domain_hi,domain_hi,domain_hi)); BoxArray bs(domain); bs.maxSize(maxGrid); // This defines the physical size of the box. Right now the box is [0,1] in each direction. RealBox real_box; for (int n = 0; n < BL_SPACEDIM; n++) { real_box.setLo(n, 0.0); real_box.setHi(n, 1.0); } // This says we are using Cartesian coordinates int coord = 0; // This sets the boundary conditions to be periodic or not int is_per[BL_SPACEDIM]; if (bc_type == Dirichlet || bc_type == Neumann) { for (int n = 0; n < BL_SPACEDIM; n++) is_per[n] = 0; } else { for (int n = 0; n < BL_SPACEDIM; n++) is_per[n] = 1; } // This defines a Geometry object which is useful for writing the plotfiles Geometry geom(domain,&real_box,coord,is_per); for ( int n=0; n<BL_SPACEDIM; n++ ) { dx[n] = ( geom.ProbHi(n) - geom.ProbLo(n) )/domain.length(n); } if (ParallelDescriptor::IOProcessor()) { std::cout << "Domain size : " << N << std::endl; std::cout << "Max_grid_size : " << maxGrid << std::endl; std::cout << "Number of grids : " << bs.size() << std::endl; } // Allocate and define the right hand side. MultiFab rhs(bs, Ncomp, 0, Fab_allocate); setup_rhs(rhs, geom, a, b); MultiFab alpha(bs, Ncomp, 0, Fab_allocate); MultiFab beta[BL_SPACEDIM]; for ( int n=0; n<BL_SPACEDIM; ++n ) { BoxArray bx(bs); beta[n].define(bx.surroundingNodes(n), Ncomp, 1, Fab_allocate); } setup_coeffs(bs, alpha, beta, geom); MultiFab anaSoln; if (comp_norm) { anaSoln.define(bs, Ncomp, 0, Fab_allocate); compute_analyticSolution(anaSoln); } // Allocate the solution array // Set the number of ghost cells in the solution array. MultiFab soln(bs, Ncomp, 1, Fab_allocate); solve(soln, anaSoln, a, b, alpha, beta, rhs, bs, geom, BoxLib_C); BL_PROFILE_VAR_STOP(pmain); BoxLib::Finalize(); }
// static QuerySolution* QueryPlannerAnalysis::analyzeDataAccess(const CanonicalQuery& query, const QueryPlannerParams& params, QuerySolutionNode* solnRoot) { auto_ptr<QuerySolution> soln(new QuerySolution()); soln->filterData = query.getQueryObj(); verify(soln->filterData.isOwned()); soln->ns = query.ns(); soln->indexFilterApplied = params.indexFiltersApplied; solnRoot->computeProperties(); // solnRoot finds all our results. Let's see what transformations we must perform to the // data. // If we're answering a query on a sharded system, we need to drop documents that aren't // logically part of our shard. if (params.options & QueryPlannerParams::INCLUDE_SHARD_FILTER) { // TODO: We could use params.shardKey to do fetch analysis instead of always fetching. if (!solnRoot->fetched()) { FetchNode* fetch = new FetchNode(); fetch->children.push_back(solnRoot); solnRoot = fetch; } ShardingFilterNode* sfn = new ShardingFilterNode(); sfn->children.push_back(solnRoot); solnRoot = sfn; } bool hasSortStage = false; solnRoot = analyzeSort(query, params, solnRoot, &hasSortStage); // This can happen if we need to create a blocking sort stage and we're not allowed to. if (NULL == solnRoot) { return NULL; } // A solution can be blocking if it has a blocking sort stage or // a hashed AND stage. bool hasAndHashStage = hasNode(solnRoot, STAGE_AND_HASH); soln->hasBlockingStage = hasSortStage || hasAndHashStage; // If we can (and should), add the keep mutations stage. // We cannot keep mutated documents if: // // 1. The query requires an index to evaluate the predicate ($text). We can't tell whether // or not the doc actually satisfies the $text predicate since we can't evaluate a // text MatchExpression. // // 2. The query implies a sort ($geoNear). It would be rather expensive and hacky to merge // the document at the right place. // // 3. There is an index-provided sort. Ditto above comment about merging. // // TODO: do we want some kind of pre-planning step where we look for certain nodes and cache // them? We do lookups in the tree a few times. This may not matter as most trees are // shallow in terms of query nodes. bool cannotKeepFlagged = hasNode(solnRoot, STAGE_TEXT) || hasNode(solnRoot, STAGE_GEO_NEAR_2D) || hasNode(solnRoot, STAGE_GEO_NEAR_2DSPHERE) || (!query.getParsed().getSort().isEmpty() && !hasSortStage); // Only these stages can produce flagged results. A stage has to hold state past one call // to work(...) in order to possibly flag a result. bool couldProduceFlagged = hasNode(solnRoot, STAGE_GEO_2D) || hasAndHashStage || hasNode(solnRoot, STAGE_AND_SORTED) || hasNode(solnRoot, STAGE_FETCH); bool shouldAddMutation = !cannotKeepFlagged && couldProduceFlagged; if (shouldAddMutation && (params.options & QueryPlannerParams::KEEP_MUTATIONS)) { KeepMutationsNode* keep = new KeepMutationsNode(); // We must run the entire expression tree to make sure the document is still valid. keep->filter.reset(query.root()->shallowClone()); if (STAGE_SORT == solnRoot->getType()) { // We want to insert the invalidated results before the sort stage, if there is one. verify(1 == solnRoot->children.size()); keep->children.push_back(solnRoot->children[0]); solnRoot->children[0] = keep; } else { keep->children.push_back(solnRoot); solnRoot = keep; } } // Project the results. if (NULL != query.getProj()) { QLOG() << "PROJECTION: fetched status: " << solnRoot->fetched() << endl; QLOG() << "PROJECTION: Current plan is:\n" << solnRoot->toString() << endl; ProjectionNode::ProjectionType projType = ProjectionNode::DEFAULT; BSONObj coveredKeyObj; if (query.getProj()->requiresDocument()) { QLOG() << "PROJECTION: claims to require doc adding fetch.\n"; // If the projection requires the entire document, somebody must fetch. if (!solnRoot->fetched()) { FetchNode* fetch = new FetchNode(); fetch->children.push_back(solnRoot); solnRoot = fetch; } } else if (!query.getProj()->wantIndexKey()) { // The only way we're here is if it's a simple projection. That is, we can pick out // the fields we want to include and they're not dotted. So we want to execute the // projection in the fast-path simple fashion. Just don't know which fast path yet. QLOG() << "PROJECTION: requires fields\n"; const vector<string>& fields = query.getProj()->getRequiredFields(); bool covered = true; for (size_t i = 0; i < fields.size(); ++i) { if (!solnRoot->hasField(fields[i])) { QLOG() << "PROJECTION: not covered due to field " << fields[i] << endl; covered = false; break; } } QLOG() << "PROJECTION: is covered?: = " << covered << endl; // If any field is missing from the list of fields the projection wants, // a fetch is required. if (!covered) { FetchNode* fetch = new FetchNode(); fetch->children.push_back(solnRoot); solnRoot = fetch; // It's simple but we'll have the full document and we should just iterate // over that. projType = ProjectionNode::SIMPLE_DOC; QLOG() << "PROJECTION: not covered, fetching."; } else { if (solnRoot->fetched()) { // Fetched implies hasObj() so let's run with that. projType = ProjectionNode::SIMPLE_DOC; QLOG() << "PROJECTION: covered via FETCH, using SIMPLE_DOC fast path"; } else { // If we're here we're not fetched so we're covered. Let's see if we can // get out of using the default projType. If there's only one leaf // underneath and it's giving us index data we can use the faster covered // impl. vector<QuerySolutionNode*> leafNodes; getLeafNodes(solnRoot, &leafNodes); if (1 == leafNodes.size()) { // Both the IXSCAN and DISTINCT stages provide covered key data. if (STAGE_IXSCAN == leafNodes[0]->getType()) { projType = ProjectionNode::COVERED_ONE_INDEX; IndexScanNode* ixn = static_cast<IndexScanNode*>(leafNodes[0]); coveredKeyObj = ixn->indexKeyPattern; QLOG() << "PROJECTION: covered via IXSCAN, using COVERED fast path"; } else if (STAGE_DISTINCT == leafNodes[0]->getType()) { projType = ProjectionNode::COVERED_ONE_INDEX; DistinctNode* dn = static_cast<DistinctNode*>(leafNodes[0]); coveredKeyObj = dn->indexKeyPattern; QLOG() << "PROJECTION: covered via DISTINCT, using COVERED fast path"; } } } } } // We now know we have whatever data is required for the projection. ProjectionNode* projNode = new ProjectionNode(); projNode->children.push_back(solnRoot); projNode->fullExpression = query.root(); projNode->projection = query.getParsed().getProj(); projNode->projType = projType; projNode->coveredKeyObj = coveredKeyObj; solnRoot = projNode; } else { // If there's no projection, we must fetch, as the user wants the entire doc. if (!solnRoot->fetched()) { FetchNode* fetch = new FetchNode(); fetch->children.push_back(solnRoot); solnRoot = fetch; } } if (0 != query.getParsed().getSkip()) { SkipNode* skip = new SkipNode(); skip->skip = query.getParsed().getSkip(); skip->children.push_back(solnRoot); solnRoot = skip; } // When there is both a blocking sort and a limit, the limit will // be enforced by the blocking sort. // Otherwise, we need to limit the results in the case of a hard limit // (ie. limit in raw query is negative) if (0 != query.getParsed().getNumToReturn() && !hasSortStage && !query.getParsed().wantMore()) { LimitNode* limit = new LimitNode(); limit->limit = query.getParsed().getNumToReturn(); limit->children.push_back(solnRoot); solnRoot = limit; } soln->root.reset(solnRoot); return soln.release(); }
int main(int argc, char* argv[]) { BoxLib::Initialize(argc,argv); BL_PROFILE_VAR("main()", pmain); std::cout << std::setprecision(15); ParmParse ppmg("mg"); ppmg.query("v", verbose); ppmg.query("maxorder", maxorder); ParmParse pp; { std::string solver_type_s; pp.get("solver_type",solver_type_s); if (solver_type_s == "BoxLib_C") { solver_type = BoxLib_C; } else if (solver_type_s == "BoxLib_C4") { solver_type = BoxLib_C4; } else if (solver_type_s == "BoxLib_F") { #ifdef USE_F90_SOLVERS solver_type = BoxLib_F; #else BoxLib::Error("Set USE_FORTRAN=TRUE in GNUmakefile"); #endif } else if (solver_type_s == "Hypre") { #ifdef USEHYPRE solver_type = Hypre; #else BoxLib::Error("Set USE_HYPRE=TRUE in GNUmakefile"); #endif } else if (solver_type_s == "All") { solver_type = All; } else { if (ParallelDescriptor::IOProcessor()) { std::cout << "Don't know this solver type: " << solver_type << std::endl; } BoxLib::Error(""); } } { std::string bc_type_s; pp.get("bc_type",bc_type_s); if (bc_type_s == "Dirichlet") { bc_type = Dirichlet; #ifdef USEHPGMG domain_boundary_condition = BC_DIRICHLET; #endif } else if (bc_type_s == "Neumann") { bc_type = Neumann; #ifdef USEHPGMG BoxLib::Error("HPGMG does not support Neumann boundary conditions"); #endif } else if (bc_type_s == "Periodic") { bc_type = Periodic; #ifdef USEHPGMG domain_boundary_condition = BC_PERIODIC; #endif } else { if (ParallelDescriptor::IOProcessor()) { std::cout << "Don't know this boundary type: " << bc_type << std::endl; } BoxLib::Error(""); } } pp.query("tol_rel", tolerance_rel); pp.query("tol_abs", tolerance_abs); pp.query("maxiter", maxiter); pp.query("plot_rhs" , plot_rhs); pp.query("plot_beta", plot_beta); pp.query("plot_soln", plot_soln); pp.query("plot_asol", plot_asol); pp.query("plot_err", plot_err); pp.query("comp_norm", comp_norm); Real a, b; pp.get("a", a); pp.get("b", b); pp.get("n_cell",n_cell); pp.get("max_grid_size",max_grid_size); // Define a single box covering the domain IntVect dom_lo(D_DECL(0,0,0)); IntVect dom_hi(D_DECL(n_cell-1,n_cell-1,n_cell-1)); Box domain(dom_lo,dom_hi); // Initialize the boxarray "bs" from the single box "bx" BoxArray bs(domain); // Break up boxarray "bs" into chunks no larger than "max_grid_size" along a direction bs.maxSize(max_grid_size); // This defines the physical size of the box. Right now the box is [0,1] in each direction. RealBox real_box; for (int n = 0; n < BL_SPACEDIM; n++) { real_box.setLo(n, 0.0); real_box.setHi(n, 1.0); } // This says we are using Cartesian coordinates int coord = 0; // This sets the boundary conditions to be periodic or not Array<int> is_per(BL_SPACEDIM,1); if (bc_type == Dirichlet || bc_type == Neumann) { if (ParallelDescriptor::IOProcessor()) { std::cout << "Using Dirichlet or Neumann boundary conditions." << std::endl; } for (int n = 0; n < BL_SPACEDIM; n++) is_per[n] = 0; } else { if (ParallelDescriptor::IOProcessor()) { std::cout << "Using periodic boundary conditions." << std::endl; } for (int n = 0; n < BL_SPACEDIM; n++) is_per[n] = 1; } // This defines a Geometry object which is useful for writing the plotfiles Geometry geom(domain,&real_box,coord,is_per.dataPtr()); for ( int n=0; n<BL_SPACEDIM; n++ ) { dx[n] = ( geom.ProbHi(n) - geom.ProbLo(n) )/domain.length(n); } if (ParallelDescriptor::IOProcessor()) { std::cout << "Grid resolution : " << n_cell << " (cells)" << std::endl; std::cout << "Domain size : " << real_box.hi(0) - real_box.lo(0) << " (length unit) " << std::endl; std::cout << "Max_grid_size : " << max_grid_size << " (cells)" << std::endl; std::cout << "Number of grids : " << bs.size() << std::endl; } // Allocate and define the right hand side. bool do_4th = (solver_type==BoxLib_C4 || solver_type==All); int ngr = (do_4th ? 1 : 0); MultiFab rhs(bs, Ncomp, ngr); setup_rhs(rhs, geom); // Set up the Helmholtz operator coefficients. MultiFab alpha(bs, Ncomp, 0); PArray<MultiFab> beta(BL_SPACEDIM, PArrayManage); for ( int n=0; n<BL_SPACEDIM; ++n ) { BoxArray bx(bs); beta.set(n, new MultiFab(bx.surroundingNodes(n), Ncomp, 0, Fab_allocate)); } // The way HPGMG stores face-centered data is completely different than the // way BoxLib does it, and translating between the two directly via indexing // magic is a nightmare. Happily, the way this tutorial calculates // face-centered values is by first calculating cell-centered values and then // interpolating to the cell faces. HPGMG can do the same thing, so rather // than converting directly from BoxLib's face-centered data to HPGMG's, just // give HPGMG the cell-centered data and let it interpolate itself. MultiFab beta_cc(bs,Ncomp,1); // cell-centered beta setup_coeffs(bs, alpha, beta, geom, beta_cc); MultiFab alpha4, beta4; if (do_4th) { alpha4.define(bs, Ncomp, 4, Fab_allocate); beta4.define(bs, Ncomp, 3, Fab_allocate); setup_coeffs4(bs, alpha4, beta4, geom); } MultiFab anaSoln; if (comp_norm || plot_err || plot_asol) { anaSoln.define(bs, Ncomp, 0, Fab_allocate); compute_analyticSolution(anaSoln,Array<Real>(BL_SPACEDIM,0.5)); if (plot_asol) { writePlotFile("ASOL", anaSoln, geom); } } // Allocate the solution array // Set the number of ghost cells in the solution array. MultiFab soln(bs, Ncomp, 1); MultiFab soln4; if (do_4th) { soln4.define(bs, Ncomp, 3, Fab_allocate); } MultiFab gphi(bs, BL_SPACEDIM, 0); #ifdef USEHYPRE if (solver_type == Hypre || solver_type == All) { if (ParallelDescriptor::IOProcessor()) { std::cout << "----------------------------------------" << std::endl; std::cout << "Solving with Hypre " << std::endl; } solve(soln, anaSoln, gphi, a, b, alpha, beta, beta_cc, rhs, bs, geom, Hypre); } #endif if (solver_type == BoxLib_C || solver_type == All) { if (ParallelDescriptor::IOProcessor()) { std::cout << "----------------------------------------" << std::endl; std::cout << "Solving with BoxLib C++ solver " << std::endl; } solve(soln, anaSoln, gphi, a, b, alpha, beta, beta_cc, rhs, bs, geom, BoxLib_C); } if (solver_type == BoxLib_C4 || solver_type == All) { if (ParallelDescriptor::IOProcessor()) { std::cout << "----------------------------------------" << std::endl; std::cout << "Solving with BoxLib C++ 4th order solver " << std::endl; } solve4(soln4, anaSoln, a, b, alpha4, beta4, rhs, bs, geom); } #ifdef USE_F90_SOLVERS if (solver_type == BoxLib_F || solver_type == All) { if (ParallelDescriptor::IOProcessor()) { std::cout << "----------------------------------------" << std::endl; std::cout << "Solving with BoxLib F90 solver " << std::endl; } solve(soln, anaSoln, gphi, a, b, alpha, beta, beta_cc, rhs, bs, geom, BoxLib_F); } #endif #ifdef USEHPGMG if (solver_type == HPGMG || solver_type == All) { if (ParallelDescriptor::IOProcessor()) { std::cout << "----------------------------------------" << std::endl; std::cout << "Solving with HPGMG solver " << std::endl; } solve(soln, anaSoln, gphi, a, b, alpha, beta, beta_cc, rhs, bs, geom, HPGMG); } #endif if (ParallelDescriptor::IOProcessor()) { std::cout << "----------------------------------------" << std::endl; } BL_PROFILE_VAR_STOP(pmain); BoxLib::Finalize(); }
int main(int argc, char**argv) { int block_sz = atoi(argv[1]); int blocks_nr = atoi(argv[2]); int edge_sz = atoi(argv[3]); std::vector<Block> bs(blocks_nr, Block(block_sz,edge_sz) ); Edge e(edge_sz,blocks_nr,block_sz); for (int i=0; i < bs.size(); ++i) bs[i].fill(); e.fill(); // for (int i=0; i < bs.size(); ++i) // std::cout << bs[i] << '\n'; // std::cout << e << '\n'; std::vector<Block> bs0 = bs; Edge e0 = e; double total_time=0.0; clock_t st, end; st = clock(); for (int i=0; i < bs.size(); ++i) bs[i].fwd(); end = clock(); total_time += double((end - st)) / CLOCKS_PER_SEC; for (int b=0; b < bs.size(); ++b) { for (int br=0; br < bs[b].rows; ++br) { double& diag = bs[b](br,br); RowNO r; r.v = &diag; r.sz = bs[b].cols-br; r.row_no = bs[b].rows*b + br; st = clock(); elim_col(e,r); end = clock(); total_time += double((end - st)) / CLOCKS_PER_SEC; } } st = clock(); e.fwd(); e.bwd(); for (int i=0; i < bs.size(); ++i){ bs[i].bwd(e.edge_soln); } end = clock(); total_time += double((end - st)) / CLOCKS_PER_SEC; std::cout << "elapsed " << total_time << '\n'; std::vector<double> soln(bs[0].rows*bs.size() + edge_sz); for (int i=0; i < bs.size(); ++i) for (int k=0; k < bs[i].sol.size(); ++k) soln[i*block_sz+k] = bs[i].sol[k]; for (int k=0; k < e.edge_soln.size(); ++k) soln[blocks_nr*block_sz+k] = e.edge_soln[k]; // for (int k=0; k < soln.size(); ++k) // std::cout << soln[k] << '\n'; std::vector<double> Rhs; for(int i = 0; i < bs0.size(); ++i) { for(int r=0; r < bs0[i].rows; ++r) Rhs.push_back(bs0[i](r,bs0[i].cols-1)); } for(int i = 0; i < e0.rows; ++i) { Rhs.push_back(e0(i,e0.cols-1)); } std::vector<double> rhs = mult(bs0,e0,soln); double residue=0.0; for (int i=0; i < rhs.size(); ++i) residue += fabs(rhs[i] - Rhs[i]); std::cout << "\n\nres = " << residue << '\n'; }
int main (int argc, char* argv[]) { BoxLib::Initialize(argc,argv); std::cout << std::setprecision(10); if (argc < 2) { std::cerr << "usage: " << argv[0] << " inputsfile [options]" << '\n'; exit(-1); } ParmParse pp; int n; BoxArray bs; #if BL_SPACEDIM == 2 Box domain(IntVect(0,0),IntVect(11,11)); std::string boxfile("gr.2_small_a") ; #elif BL_SPACEDIM == 3 Box domain(IntVect(0,0,0),IntVect(11,11,11)); std::string boxfile("grids/gr.3_2x3x4") ; #endif pp.query("boxes", boxfile); std::ifstream ifs(boxfile.c_str(), std::ios::in); if (!ifs) { std::string msg = "problem opening grids file: "; msg += boxfile.c_str(); BoxLib::Abort(msg.c_str()); } ifs >> domain; if (ParallelDescriptor::IOProcessor()) std::cout << "domain: " << domain << std::endl; bs.readFrom(ifs); if (ParallelDescriptor::IOProcessor()) std::cout << "grids:\n" << bs << std::endl; Geometry geom(domain); const Real* H = geom.CellSize(); int ratio=2; pp.query("ratio", ratio); // allocate/init soln and rhs int Ncomp=BL_SPACEDIM; int Nghost=0; int Ngrids=bs.size(); MultiFab soln(bs, Ncomp, Nghost, Fab_allocate); soln.setVal(0.0); MultiFab out(bs, Ncomp, Nghost, Fab_allocate); MultiFab rhs(bs, Ncomp, Nghost, Fab_allocate); rhs.setVal(0.0); for(MFIter rhsmfi(rhs); rhsmfi.isValid(); ++rhsmfi) { FORT_FILLRHS(rhs[rhsmfi].dataPtr(), ARLIM(rhs[rhsmfi].loVect()),ARLIM(rhs[rhsmfi].hiVect()), H,&Ncomp); } // Create the boundary object MCViscBndry vbd(bs,geom); BCRec phys_bc; Array<int> lo_bc(BL_SPACEDIM), hi_bc(BL_SPACEDIM); pp.getarr("lo_bc",lo_bc,0,BL_SPACEDIM); pp.getarr("hi_bc",hi_bc,0,BL_SPACEDIM); for (int i = 0; i < BL_SPACEDIM; i++) { phys_bc.setLo(i,lo_bc[i]); phys_bc.setHi(i,hi_bc[i]); } // Create the BCRec's interpreted by ViscBndry objects #if BL_SPACEDIM==2 Array<BCRec> pbcarray(4); pbcarray[0] = BCRec(D_DECL(REFLECT_ODD,REFLECT_EVEN,EXT_DIR), D_DECL(EXT_DIR,EXT_DIR,EXT_DIR)); pbcarray[1] = BCRec(D_DECL(REFLECT_EVEN,REFLECT_ODD,EXT_DIR), D_DECL(EXT_DIR,EXT_DIR,EXT_DIR)); pbcarray[2] = BCRec(D_DECL(EXT_DIR,EXT_DIR,EXT_DIR), D_DECL(EXT_DIR,EXT_DIR,EXT_DIR)); pbcarray[3] = BCRec(D_DECL(EXT_DIR,EXT_DIR,EXT_DIR), D_DECL(EXT_DIR,EXT_DIR,EXT_DIR)); #elif BL_SPACEDIM==3 Array<BCRec> pbcarray(12); #if 1 pbcarray[0] = BCRec(EXT_DIR,EXT_DIR,EXT_DIR,EXT_DIR,EXT_DIR,EXT_DIR); pbcarray[1] = BCRec(EXT_DIR,EXT_DIR,EXT_DIR,EXT_DIR,EXT_DIR,EXT_DIR); pbcarray[2] = BCRec(EXT_DIR,EXT_DIR,EXT_DIR,EXT_DIR,EXT_DIR,EXT_DIR); pbcarray[3] = BCRec(D_DECL(EXT_DIR,EXT_DIR,EXT_DIR), D_DECL(EXT_DIR,EXT_DIR,EXT_DIR)); pbcarray[4] = BCRec(D_DECL(EXT_DIR,EXT_DIR,EXT_DIR), D_DECL(EXT_DIR,EXT_DIR,EXT_DIR)); pbcarray[5] = BCRec(D_DECL(EXT_DIR,EXT_DIR,EXT_DIR), D_DECL(EXT_DIR,EXT_DIR,EXT_DIR)); pbcarray[6] = BCRec(D_DECL(EXT_DIR,EXT_DIR,EXT_DIR), D_DECL(EXT_DIR,EXT_DIR,EXT_DIR)); pbcarray[7] = BCRec(D_DECL(EXT_DIR,EXT_DIR,EXT_DIR), D_DECL(EXT_DIR,EXT_DIR,EXT_DIR)); pbcarray[8] = BCRec(D_DECL(EXT_DIR,EXT_DIR,EXT_DIR), D_DECL(EXT_DIR,EXT_DIR,EXT_DIR)); pbcarray[9] = BCRec(D_DECL(EXT_DIR,EXT_DIR,EXT_DIR), D_DECL(EXT_DIR,EXT_DIR,EXT_DIR)); pbcarray[10] = BCRec(D_DECL(EXT_DIR,EXT_DIR,EXT_DIR), D_DECL(EXT_DIR,EXT_DIR,EXT_DIR)); pbcarray[11] = BCRec(D_DECL(EXT_DIR,EXT_DIR,EXT_DIR), D_DECL(EXT_DIR,EXT_DIR,EXT_DIR)); #else for (int i = 0; i < 12; i++) pbcarray[i] = phys_bc; #endif #endif Nghost = 1; // need space for bc info MultiFab fine(bs,Ncomp,Nghost,Fab_allocate); for(MFIter finemfi(fine); finemfi.isValid(); ++finemfi) { FORT_FILLFINE(fine[finemfi].dataPtr(), ARLIM(fine[finemfi].loVect()),ARLIM(fine[finemfi].hiVect()), H,&Ncomp); } // Create "background coarse data" Box crse_bx = Box(domain).coarsen(ratio).grow(1); BoxArray cba(crse_bx); cba.maxSize(32); Real h_crse[BL_SPACEDIM]; for (n=0; n<BL_SPACEDIM; n++) h_crse[n] = H[n]*ratio; MultiFab crse_mf(cba, Ncomp, 0); // FArrayBox crse_fab(crse_bx,Ncomp); for (MFIter mfi(crse_mf); mfi.isValid(); ++mfi) { FORT_FILLCRSE(crse_mf[mfi].dataPtr(), ARLIM(crse_mf[mfi].loVect()),ARLIM(crse_mf[mfi].hiVect()), h_crse,&Ncomp); } // Create coarse boundary register, fill w/data from coarse FAB int bndry_InRad=0; int bndry_OutRad=1; int bndry_Extent=1; BoxArray cbs = BoxArray(bs).coarsen(ratio); BndryRegister cbr(cbs,bndry_InRad,bndry_OutRad,bndry_Extent,Ncomp); for (OrientationIter face; face; ++face) { Orientation f = face(); FabSet& bnd_fs(cbr[f]); bnd_fs.copyFrom(crse_mf, 0, 0, 0, Ncomp); } // Interpolate crse data to fine boundary, where applicable int cbr_Nstart=0; int fine_Nstart=0; int bndry_Nstart=0; vbd.setBndryValues(cbr,cbr_Nstart,fine,fine_Nstart, bndry_Nstart,Ncomp,ratio,pbcarray); Nghost = 1; // other variables don't need extra space DivVis lp(vbd,H); Real a = 0.0; Real b[BL_SPACEDIM]; b[0] = 1.0; b[1] = 1.0; #if BL_SPACEDIM>2 b[2] = 1.0; #endif MultiFab acoefs; int NcompA = (BL_SPACEDIM == 2 ? 2 : 1); acoefs.define(bs, NcompA, Nghost, Fab_allocate); acoefs.setVal(a); MultiFab bcoefs[BL_SPACEDIM]; for (n=0; n<BL_SPACEDIM; ++n) { BoxArray bsC(bs); bcoefs[n].define(bsC.surroundingNodes(n), 1, Nghost, Fab_allocate); #if 1 for(MFIter bmfi(bcoefs[n]); bmfi.isValid(); ++bmfi) { FORT_MAKEMU(bcoefs[n][bmfi].dataPtr(), ARLIM(bcoefs[n][bmfi].loVect()),ARLIM(bcoefs[n][bmfi].hiVect()),H,n); } #else bcoefs[n].setVal(b[n]); #endif } // -->> over dimension lp.setCoefficients(acoefs, bcoefs); #if 1 lp.maxOrder(4); #endif Nghost = 1; MultiFab tsoln(bs, Ncomp, Nghost, Fab_allocate); tsoln.setVal(0.0); #if 1 tsoln.copy(fine); #endif #if 0 // testing apply lp.apply(out,tsoln); Box subbox = out[0].box(); Real n1 = out[0].norm(subbox,1,0,BL_SPACEDIM)*pow(H[0],BL_SPACEDIM); ParallelDescriptor::ReduceRealSum(n1); if (ParallelDescriptor::IOProcessor()) { cout << "n1 output is "<<n1<<std::endl; } out.minus(rhs,0,BL_SPACEDIM,0); // special to single grid prob Real n2 = out[0].norm(subbox,1,0,BL_SPACEDIM)*pow(H[0],BL_SPACEDIM); ParallelDescriptor::ReduceRealSum(n2); if (ParallelDescriptor::IOProcessor()) { cout << "n2 difference is "<<n2<<std::endl; } #if 0 subbox.grow(-1); Real n3 = out[0].norm(subbox,0,0,BL_SPACEDIM)*pow(H[0],BL_SPACEDIM); ParallelDescriptor::ReduceRealMax(n3); if (ParallelDescriptor::IOProcessor()) { cout << "n3 difference is "<<n3<<std::endl; } #endif #endif const IntVect refRatio(D_DECL(2,2,2)); const Real bgVal = 1.0; #if 1 #ifndef NDEBUG // testing flux computation BoxArray xfluxbox(bs); xfluxbox.surroundingNodes(0); MultiFab xflux(xfluxbox,Ncomp,Nghost,Fab_allocate); xflux.setVal(1.e30); BoxArray yfluxbox(bs); yfluxbox.surroundingNodes(1); MultiFab yflux(yfluxbox,Ncomp,Nghost,Fab_allocate); yflux.setVal(1.e30); #if BL_SPACEDIM>2 BoxArray zfluxbox(bs); zfluxbox.surroundingNodes(2); MultiFab zflux(zfluxbox,Ncomp,Nghost,Fab_allocate); zflux.setVal(1.e30); #endif lp.compFlux(xflux, yflux, #if BL_SPACEDIM>2 zflux, #endif tsoln); // Write fluxes //writeMF(&xflux,"xflux.mfab"); //writeMF(&yflux,"yflux.mfab"); #if BL_SPACEDIM>2 //writeMF(&zflux,"zflux.mfab"); #endif #endif #endif Real tolerance = 1.0e-10; pp.query("tol", tolerance); Real tolerance_abs = 1.0e-10; pp.query("tol_abs", tolerance_abs); #if 0 cout << "Bndry Data object:" << std::endl; cout << lp.bndryData() << std::endl; #endif #if 0 bool use_mg_pre = false; MCCGSolver cg(lp,use_mg_pre); cg.solve(soln,rhs,tolerance,tolerance_abs); #else MCMultiGrid mg(lp); mg.solve(soln,rhs,tolerance,tolerance_abs); #endif #if 0 cout << "MCLinOp object:" << std::endl; cout << lp << std::endl; #endif VisMF::Write(soln,"soln"); #if 0 // apply operator to soln to see if really satisfies eqn tsoln.copy(soln); lp.apply(out,tsoln); soln.copy(out); // Output "apply" results on soln VisMF::Write(soln,"apply"); // Compute truncation for (MFIter smfi(soln); smfi.isValid(); ++smfi) { soln[smfi] -= fine[smfi]; } for( int icomp=0; icomp < BL_SPACEDIM ; icomp++ ) { Real solnMin = soln.min(icomp); Real solnMax = soln.max(icomp); ParallelDescriptor::ReduceRealMin(solnMin); ParallelDescriptor::ReduceRealMax(solnMax); if (ParallelDescriptor::IOProcessor()) { cout << icomp << " "<<solnMin << " " << solnMax <<std::endl; } } // Output truncation VisMF::Write(soln,"trunc"); #endif int dumpLp=0; pp.query("dumpLp",dumpLp); bool write_lp = (dumpLp == 1 ? true : false); if (write_lp) std::cout << lp << std::endl; // Output trunc ParallelDescriptor::EndParallel(); }