void solverloop(int start, int end){ int i, j; int indx, indx_up, indx_lft; int indx_rght, indx_up, indx_dwn; double phi,dphi_dt,dmu_dt; double drv_frce, alln_chn; double Gamma, kai; double dc_dx, dc_dy, V_gradC; #ifdef ANISO grad_phi(1, dphi_now); #endif for (i=start; i < end; i++) { #ifdef ANISO grad_phi(i+1, dphi_next); #endif for (j=1; j < (MESHX-1); j++){ indx = i*MESHX + j; indx_lft = indx - 1; indx_rght = indx + 1; indx_up = indx - MESHX; indx_dwn = indx + MESHX; phi = phi_old[indx]; #ifdef ISO Gamma = 2*G*lap_phi[indx]; #endif #ifdef ANISO Gamma = div_phi(j); #endif drv_frce = (mu_old[indx] - Mu)*(K-1)*(mu_old[indx])*6*phi*(1-phi); alln_chn = E*Gamma - (G/E)*18.0*(phi)*(1.0-phi)*(1.0-2.0*phi); dp_dt = (alln_chn + drv_frce)/(tau*E); phi_new[z] = phi + deltat*dphi_dt; #ifdef ANISO dc_dx = (conc[indx_rght] - conc[indx_lft])*0.5*inv_deltax; dc_dy = (conc[indx_dwn] - conc[indx_up] )*0.5*inv_deltax; V_gradC = u_old[indx]*dc_dx + v_old[indx]*dc_dy; #endif #ifdef ISO V_gradC = 0.0; #endif dmu_dt = Mob*lap_mu[indx] - V_gradC - (K-1)*mu_old[indx]*6*phi*(1-phi)*dphi_dt; kai = 1+(K-1)*phi*phi*(3-2*phi); mu_new[indx] = mu_old[indx] + deltat*dmu_dt/kai; } #ifdef ANISO fnupdate(); #endif } }
void solverloop(){ int i, j, z; double p,dp_dt,dmu_dt; double drv_frce, alln_chn; double Gamma, kai; double dc_dx, dc_dy, V_gradC = 0.0; #ifdef ANISO grad_phi(1, dphi_now); #endif for (i=start; i <= end; i++) { #ifdef ANISO grad_phi(i+1, dphi_next); #endif for (j=1; j < (MESHX-1); j++){ z = i*MESHX + j; p = phi_old[z]; #ifdef ISO Gamma = 2*G*lap_phi[z]; #endif #ifdef ANISO Gamma = div_phi(j); #endif drv_frce = (mu_old[z] - Mu)*(K-1)*(mu_old[z])*6*p*(1-p); alln_chn = E*Gamma - (G/E)*18.0*(p)*(1.0-p)*(1.0-2.0*p); dp_dt = (alln_chn + drv_frce)/(tau*E); phi_new[z] = p + deltat*dp_dt; #ifdef FLUID dc_dx = (conc[z+1]-conc[z-1])*0.5*inv_deltax; dc_dy = (conc[z+MESHX]-conc[z-MESHX])*0.5*inv_deltax; V_gradC = u_old[z]*dc_dx + v_old[z]*dc_dy; #endif dmu_dt = Mob*lap_mu[z] - V_gradC - (K-1)*mu_old[z]*6*p*(1-p)*dp_dt; kai = 1+(K-1)*p*p*(3-2*p); mu_new[z] = mu_old[z] + deltat*dmu_dt/kai; } #ifdef ANISO fnupdate(); #endif } }
void solve_with_Cpp(MultiFab& soln, MultiFab& gphi, Real a, Real b, MultiFab& alpha, PArray<MultiFab>& beta, MultiFab& rhs, const BoxArray& bs, const Geometry& geom) { BL_PROFILE("solve_with_Cpp()"); BndryData bd(bs, 1, geom); set_boundary(bd, rhs, 0); ABecLaplacian abec_operator(bd, dx); abec_operator.setScalars(a, b); abec_operator.setCoefficients(alpha, beta); MultiGrid mg(abec_operator); mg.setVerbose(verbose); mg.solve(soln, rhs, tolerance_rel, tolerance_abs); PArray<MultiFab> grad_phi(BL_SPACEDIM, PArrayManage); for (int n = 0; n < BL_SPACEDIM; ++n) grad_phi.set(n, new MultiFab(BoxArray(soln.boxArray()).surroundingNodes(n), 1, 0)); #if (BL_SPACEDIM == 2) abec_operator.compFlux(grad_phi[0],grad_phi[1],soln); #elif (BL_SPACEDIM == 3) abec_operator.compFlux(grad_phi[0],grad_phi[1],grad_phi[2],soln); #endif // Average edge-centered gradients to cell centers. BoxLib::average_face_to_cellcenter(gphi, grad_phi, geom); }
void solve_with_F90(MultiFab& soln, MultiFab& gphi, Real a, Real b, MultiFab& alpha, PArray<MultiFab>& beta, MultiFab& rhs, const BoxArray& bs, const Geometry& geom) { BL_PROFILE("solve_with_F90()"); FMultiGrid fmg(geom); int mg_bc[2*BL_SPACEDIM]; if (bc_type == Periodic) { // Define the type of boundary conditions to be periodic for ( int n = 0; n < BL_SPACEDIM; ++n ) { mg_bc[2*n + 0] = MGT_BC_PER; mg_bc[2*n + 1] = MGT_BC_PER; } } else if (bc_type == Neumann) { // Define the type of boundary conditions to be Neumann for ( int n = 0; n < BL_SPACEDIM; ++n ) { mg_bc[2*n + 0] = MGT_BC_NEU; mg_bc[2*n + 1] = MGT_BC_NEU; } } else if (bc_type == Dirichlet) { // Define the type of boundary conditions to be Dirichlet for ( int n = 0; n < BL_SPACEDIM; ++n ) { mg_bc[2*n + 0] = MGT_BC_DIR; mg_bc[2*n + 1] = MGT_BC_DIR; } } fmg.set_bc(mg_bc); fmg.set_maxorder(maxorder); fmg.set_scalars(a, b); fmg.set_coefficients(alpha, beta); int always_use_bnorm = 0; int need_grad_phi = 1; fmg.solve(soln, rhs, tolerance_rel, tolerance_abs, always_use_bnorm, need_grad_phi); PArray<MultiFab> grad_phi(BL_SPACEDIM, PArrayManage); for (int n = 0; n < BL_SPACEDIM; ++n) grad_phi.set(n, new MultiFab(BoxArray(soln.boxArray()).surroundingNodes(n), 1, 0)); fmg.get_fluxes(grad_phi); // Average edge-centered gradients to cell centers. BoxLib::average_face_to_cellcenter(gphi, grad_phi, geom); }
KOKKOS_INLINE_FUNCTION void FEInterpolation<EvalT, Traits>::operator () (const int i) const { for (PHX::index_size_type qp = 0; qp < num_qp; ++qp) { val_qp(i,qp) = 0.0; for (PHX::index_size_type dim = 0; dim < num_dim; ++dim) val_grad_qp(i,qp,dim) = 0.0; // Sum nodal contributions to qp for (PHX::index_size_type node = 0; node < num_nodes; ++node) { val_qp(i,qp) += phi(qp, node) * val_node(i,node); for (PHX::index_size_type dim = 0; dim < num_dim; ++dim) val_grad_qp(i,qp,dim) += grad_phi(qp, node, dim) * val_node(i,node); } } }
//********************************************************************** PHX_EVALUATE_FIELDS(FEInterpolation,cell_data) { std::vector<Element_Linear2D>::iterator cell_it = cell_data.begin; // Loop over number of cells for (std::size_t cell = 0; cell < cell_data.num_cells; ++cell) { const shards::Array<double,shards::NaturalOrder,QuadPoint,Node>& phi = cell_it->basisFunctions(); const shards::Array<double,shards::NaturalOrder,QuadPoint,Node,Dim>& grad_phi = cell_it->basisFunctionGradientsRealSpace(); // Loop over quad points of cell for (int qp = 0; qp < num_qp; ++qp) { val_qp(cell,qp) = 0.0; for (int dim = 0; dim < num_dim; ++dim) val_grad_qp(cell,qp,dim) = 0.0; // Sum nodal contributions to qp for (int node = 0; node < num_nodes; ++node) { val_qp(cell,qp) += phi(qp,node) * val_node(cell,node); for (int dim = 0; dim < num_dim; ++dim) val_grad_qp(cell,qp,dim) += grad_phi(qp,node,dim) * val_node(cell,node); } } ++cell_it; } // std::cout << "FEINterpolation: val_node" << std::endl; // val_node.print(std::cout,true); // std::cout << "FEINterpolation: val_qp" << std::endl; // val_qp.print(std::cout,true); // std::cout << "FEINterpolation: val_grad_qp" << std::endl; // val_grad_qp.print(std::cout,true); }
void CellwiseDataGradient<DIM>::SetupGradients(AbstractCellPopulation<DIM>& rCellPopulation, const std::string& rItemName) { MeshBasedCellPopulation<DIM>* pCellPopulation = static_cast<MeshBasedCellPopulation<DIM>*>(&(rCellPopulation)); TetrahedralMesh<DIM,DIM>& r_mesh = pCellPopulation->rGetMesh(); // Initialise gradients size unsigned num_nodes = pCellPopulation->GetNumNodes(); mGradients.resize(num_nodes, zero_vector<double>(DIM)); // The constant gradients at each element std::vector<c_vector<double, DIM> > gradients_on_elements; unsigned num_elements = r_mesh.GetNumElements(); gradients_on_elements.resize(num_elements, zero_vector<double>(DIM)); // The number of elements containing a given node (excl ghost elements) std::vector<unsigned> num_real_elems_for_node(num_nodes, 0); for (unsigned elem_index=0; elem_index<num_elements; elem_index++) { Element<DIM,DIM>& r_elem = *(r_mesh.GetElement(elem_index)); // Calculate the basis functions at any point (eg zero) in the element c_matrix<double, DIM, DIM> jacobian, inverse_jacobian; double jacobian_det; r_mesh.GetInverseJacobianForElement(elem_index, jacobian, jacobian_det, inverse_jacobian); const ChastePoint<DIM> zero_point; c_matrix<double, DIM, DIM+1> grad_phi; LinearBasisFunction<DIM>::ComputeTransformedBasisFunctionDerivatives(zero_point, inverse_jacobian, grad_phi); bool is_ghost_element = false; for (unsigned node_index=0; node_index<DIM+1; node_index++) { unsigned node_global_index = r_elem.GetNodeGlobalIndex(node_index); // This code is commented because CellData can't deal with ghost nodes see #1975 assert(pCellPopulation->IsGhostNode(node_global_index) == false); //// Check whether ghost element //if (pCellPopulation->IsGhostNode(node_global_index) == true) //{ // is_ghost_element = true; // break; //} // If no ghost element, get PDE solution CellPtr p_cell = pCellPopulation->GetCellUsingLocationIndex(node_global_index); double pde_solution = p_cell->GetCellData()->GetItem(rItemName); // Interpolate gradient for (unsigned i=0; i<DIM; i++) { gradients_on_elements[elem_index](i) += pde_solution* grad_phi(i, node_index); } } // Add gradient at element to gradient at node if (!is_ghost_element) { for (unsigned node_index=0; node_index<DIM+1; node_index++) { unsigned node_global_index = r_elem.GetNodeGlobalIndex(node_index); mGradients[node_global_index] += gradients_on_elements[elem_index]; num_real_elems_for_node[node_global_index]++; } } } // Divide to obtain average gradient for (typename AbstractCellPopulation<DIM>::Iterator cell_iter = pCellPopulation->Begin(); cell_iter != pCellPopulation->End(); ++cell_iter) { unsigned node_global_index = pCellPopulation->GetLocationIndexUsingCell(*cell_iter); if (!num_real_elems_for_node[node_global_index] > 0) { NEVER_REACHED; // This code is commented because CellwiseData Can't deal with ghost nodes so won't ever come into this statement see #1975 //// The node is a real node which is not in any real element //// but should be connected to some cells (if more than one cell in mesh) //Node<DIM>& this_node = *(pCellPopulation->GetNodeCorrespondingToCell(*cell_iter)); // //mGradients[node_global_index] = zero_vector<double>(DIM); //unsigned num_real_adjacent_nodes = 0; // //// Get all the adjacent nodes which correspond to real cells //std::set<Node<DIM>*> real_adjacent_nodes; //real_adjacent_nodes.clear(); // //// First loop over containing elements //for (typename Node<DIM>::ContainingElementIterator element_iter = this_node.ContainingElementsBegin(); // element_iter != this_node.ContainingElementsEnd(); // ++element_iter) //{ // // Then loop over nodes therein // Element<DIM,DIM>& r_adjacent_elem = *(r_mesh.GetElement(*element_iter)); // for (unsigned local_node_index=0; local_node_index<DIM+1; local_node_index++) // { // unsigned adjacent_node_global_index = r_adjacent_elem.GetNodeGlobalIndex(local_node_index); // // // If not a ghost node and not the node we started with // if ( !(pCellPopulation->IsGhostNode(adjacent_node_global_index)) // && adjacent_node_global_index != node_global_index ) // { // // // Calculate the contribution of gradient from this node // Node<DIM>& adjacent_node = *(r_mesh.GetNode(adjacent_node_global_index)); // // double this_cell_concentration = CellwiseData<DIM>::Instance()->GetValue(*cell_iter, 0); // CellPtr p_adjacent_cell = pCellPopulation->GetCellUsingLocationIndex(adjacent_node_global_index); // double adjacent_cell_concentration = CellwiseData<DIM>::Instance()->GetValue(p_adjacent_cell, 0); // // c_vector<double, DIM> gradient_contribution = zero_vector<double>(DIM); // // if (fabs(this_cell_concentration-adjacent_cell_concentration) > 100*DBL_EPSILON) // { // c_vector<double, DIM> edge_vector = r_mesh.GetVectorFromAtoB(this_node.rGetLocation(), adjacent_node.rGetLocation()); // double norm_edge_vector = norm_2(edge_vector); // gradient_contribution = edge_vector // * (adjacent_cell_concentration - this_cell_concentration) // / (norm_edge_vector * norm_edge_vector); // } // // mGradients[node_global_index] += gradient_contribution; // num_real_adjacent_nodes++; // } // } //} //mGradients[node_global_index] /= num_real_adjacent_nodes; } else { mGradients[node_global_index] /= num_real_elems_for_node[node_global_index]; } } }
void solve_with_HPGMG(MultiFab& soln, MultiFab& gphi, Real a, Real b, MultiFab& alpha, PArray<MultiFab>& beta, MultiFab& beta_cc, MultiFab& rhs, const BoxArray& bs, const Geometry& geom, int n_cell) { BndryData bd(bs, 1, geom); set_boundary(bd, rhs, 0); ABecLaplacian abec_operator(bd, dx); abec_operator.setScalars(a, b); abec_operator.setCoefficients(alpha, beta); int minCoarseDim; if (domain_boundary_condition == BC_PERIODIC) { minCoarseDim = 2; // avoid problems with black box calculation of D^{-1} for poisson with periodic BC's on a 1^3 grid } else { minCoarseDim = 1; // assumes you can drop order on the boundaries } level_type level_h; mg_type MG_h; int numVectors = 12; int my_rank = 0, num_ranks = 1; #ifdef BL_USE_MPI MPI_Comm_size (MPI_COMM_WORLD, &num_ranks); MPI_Comm_rank (MPI_COMM_WORLD, &my_rank); #endif /* BL_USE_MPI */ const double h0 = dx[0]; // Create the geometric structure of the HPGMG grid using the RHS MultiFab as // a template. This doesn't copy any actual data. CreateHPGMGLevel(&level_h, rhs, n_cell, max_grid_size, my_rank, num_ranks, domain_boundary_condition, numVectors, h0); // Set up the coefficients for the linear operator L. SetupHPGMGCoefficients(a, b, alpha, beta_cc, &level_h); // Now that the HPGMG grid is built, populate it with RHS data. ConvertToHPGMGLevel(rhs, n_cell, max_grid_size, &level_h, VECTOR_F); #ifdef USE_HELMHOLTZ if (ParallelDescriptor::IOProcessor()) { std::cout << "Creating Helmholtz (a=" << a << ", b=" << b << ") test problem" << std::endl;; } #else if (ParallelDescriptor::IOProcessor()) { std::cout << "Creating Poisson (a=" << a << ", b=" << b << ") test problem" << std::endl;; } #endif /* USE_HELMHOLTZ */ if (level_h.boundary_condition.type == BC_PERIODIC) { double average_value_of_f = mean (&level_h, VECTOR_F); if (average_value_of_f != 0.0) { if (ParallelDescriptor::IOProcessor()) { std::cerr << "WARNING: Periodic boundary conditions, but f does not sum to zero... mean(f)=" << average_value_of_f << std::endl; } //shift_vector(&level_h,VECTOR_F,VECTOR_F,-average_value_of_f); } } //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - rebuild_operator(&level_h,NULL,a,b); // i.e. calculate Dinv and lambda_max MGBuild(&MG_h,&level_h,a,b,minCoarseDim,ParallelDescriptor::Communicator()); // build the Multigrid Hierarchy //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - if (ParallelDescriptor::IOProcessor()) std::cout << std::endl << std::endl << "===== STARTING SOLVE =====" << std::endl << std::flush; MGResetTimers (&MG_h); zero_vector (MG_h.levels[0], VECTOR_U); #ifdef USE_FCYCLES FMGSolve (&MG_h, 0, VECTOR_U, VECTOR_F, a, b, tolerance_abs, tolerance_rel); #else MGSolve (&MG_h, 0, VECTOR_U, VECTOR_F, a, b, tolerance_abs, tolerance_rel); #endif /* USE_FCYCLES */ MGPrintTiming (&MG_h, 0); // don't include the error check in the timing results //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - if (ParallelDescriptor::IOProcessor()) std::cout << std::endl << std::endl << "===== Performing Richardson error analysis ==========================" << std::endl; // solve A^h u^h = f^h // solve A^2h u^2h = f^2h // solve A^4h u^4h = f^4h // error analysis... MGResetTimers(&MG_h); const double dtol = tolerance_abs; const double rtol = tolerance_rel; int l;for(l=0;l<3;l++){ if(l>0)restriction(MG_h.levels[l],VECTOR_F,MG_h.levels[l-1],VECTOR_F,RESTRICT_CELL); zero_vector(MG_h.levels[l],VECTOR_U); #ifdef USE_FCYCLES FMGSolve(&MG_h,l,VECTOR_U,VECTOR_F,a,b,dtol,rtol); #else MGSolve(&MG_h,l,VECTOR_U,VECTOR_F,a,b,dtol,rtol); #endif } richardson_error(&MG_h,0,VECTOR_U); // Now convert solution from HPGMG back to rhs MultiFab. ConvertFromHPGMGLevel(soln, &level_h, VECTOR_U); const double norm_from_HPGMG = norm(&level_h, VECTOR_U); const double mean_from_HPGMG = mean(&level_h, VECTOR_U); const Real norm0 = soln.norm0(); const Real norm2 = soln.norm2(); if (ParallelDescriptor::IOProcessor()) { std::cout << "mean from HPGMG: " << mean_from_HPGMG << std::endl; std::cout << "norm from HPGMG: " << norm_from_HPGMG << std::endl; std::cout << "norm0 of RHS copied to MF: " << norm0 << std::endl; std::cout << "norm2 of RHS copied to MF: " << norm2 << std::endl; } // Write the MF to disk for comparison with the in-house solver if (plot_soln) { writePlotFile("SOLN-HPGMG", soln, geom); } //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - MGDestroy(&MG_h); destroy_level(&level_h); //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - PArray<MultiFab> grad_phi(BL_SPACEDIM, PArrayManage); for (int n = 0; n < BL_SPACEDIM; ++n) grad_phi.set(n, new MultiFab(BoxArray(soln.boxArray()).surroundingNodes(n), 1, 0)); #if (BL_SPACEDIM == 2) abec_operator.compFlux(grad_phi[0],grad_phi[1],soln); #elif (BL_SPACEDIM == 3) abec_operator.compFlux(grad_phi[0],grad_phi[1],grad_phi[2],soln); #endif // Average edge-centered gradients to cell centers. BoxLib::average_face_to_cellcenter(gphi, grad_phi, geom); }
double AbstractFunctionalCalculator<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM>::CalculateOnElement(Element<ELEMENT_DIM, SPACE_DIM>& rElement) { double result_on_element = 0; // Third order quadrature. Note that the functional may be non-polynomial (see documentation of class). GaussianQuadratureRule<ELEMENT_DIM> quad_rule(3); /// NOTE: This assumes that the Jacobian is constant on an element, ie /// no curvilinear bases were used for position double jacobian_determinant; c_matrix<double, SPACE_DIM, ELEMENT_DIM> jacobian; c_matrix<double, ELEMENT_DIM, SPACE_DIM> inverse_jacobian; rElement.CalculateInverseJacobian(jacobian, jacobian_determinant, inverse_jacobian); const unsigned num_nodes = rElement.GetNumNodes(); // Loop over Gauss points for (unsigned quad_index=0; quad_index < quad_rule.GetNumQuadPoints(); quad_index++) { const ChastePoint<ELEMENT_DIM>& quad_point = quad_rule.rGetQuadPoint(quad_index); c_vector<double, ELEMENT_DIM+1> phi; LinearBasisFunction<ELEMENT_DIM>::ComputeBasisFunctions(quad_point, phi); c_matrix<double, ELEMENT_DIM, ELEMENT_DIM+1> grad_phi; LinearBasisFunction<ELEMENT_DIM>::ComputeTransformedBasisFunctionDerivatives(quad_point, inverse_jacobian, grad_phi); // Location of the Gauss point in the original element will be stored in x ChastePoint<SPACE_DIM> x(0,0,0); c_vector<double,PROBLEM_DIM> u = zero_vector<double>(PROBLEM_DIM); c_matrix<double,PROBLEM_DIM,SPACE_DIM> grad_u = zero_matrix<double>(PROBLEM_DIM,SPACE_DIM); for (unsigned i=0; i<num_nodes; i++) { const c_vector<double, SPACE_DIM>& r_node_loc = rElement.GetNode(i)->rGetLocation(); // Interpolate x x.rGetLocation() += phi(i)*r_node_loc; // Interpolate u and grad u unsigned node_global_index = rElement.GetNodeGlobalIndex(i); for (unsigned index_of_unknown=0; index_of_unknown<PROBLEM_DIM; index_of_unknown++) { // NOTE - following assumes that, if say there are two unknowns u and v, they // are stored in the current solution vector as // [U1 V1 U2 V2 ... U_n V_n] unsigned index_into_vec = PROBLEM_DIM*node_global_index + index_of_unknown; double u_at_node = mSolutionReplicated[index_into_vec]; u(index_of_unknown) += phi(i)*u_at_node; for (unsigned j=0; j<SPACE_DIM; j++) { grad_u(index_of_unknown,j) += grad_phi(j,i)*u_at_node; } } } double wJ = jacobian_determinant * quad_rule.GetWeight(quad_index); result_on_element += GetIntegrand(x, u, grad_u) * wJ; } return result_on_element; }