void AssembleOptimization::assemble_A_and_F() { A_matrix->zero(); F_vector->zero(); const MeshBase & mesh = _sys.get_mesh(); const unsigned int dim = mesh.mesh_dimension(); const unsigned int u_var = _sys.variable_number ("u"); const DofMap & dof_map = _sys.get_dof_map(); FEType fe_type = dof_map.variable_type(u_var); UniquePtr<FEBase> fe (FEBase::build(dim, fe_type)); QGauss qrule (dim, fe_type.default_quadrature_order()); fe->attach_quadrature_rule (&qrule); const std::vector<Real> & JxW = fe->get_JxW(); const std::vector<std::vector<Real> > & phi = fe->get_phi(); const std::vector<std::vector<RealGradient> > & dphi = fe->get_dphi(); std::vector<dof_id_type> dof_indices; DenseMatrix<Number> Ke; DenseVector<Number> Fe; MeshBase::const_element_iterator el = mesh.active_local_elements_begin(); const MeshBase::const_element_iterator end_el = mesh.active_local_elements_end(); for ( ; el != end_el; ++el) { const Elem * elem = *el; dof_map.dof_indices (elem, dof_indices); const unsigned int n_dofs = dof_indices.size(); fe->reinit (elem); Ke.resize (n_dofs, n_dofs); Fe.resize (n_dofs); for (unsigned int qp=0; qp<qrule.n_points(); qp++) { for (unsigned int dof_i=0; dof_i<n_dofs; dof_i++) { for (unsigned int dof_j=0; dof_j<n_dofs; dof_j++) { Ke(dof_i, dof_j) += JxW[qp] * (dphi[dof_j][qp]* dphi[dof_i][qp]); } Fe(dof_i) += JxW[qp] * phi[dof_i][qp]; } } A_matrix->add_matrix (Ke, dof_indices); F_vector->add_vector (Fe, dof_indices); } A_matrix->close(); F_vector->close(); }
void AssembleOptimization::gradient (const NumericVector<Number> & soln, NumericVector<Number> & grad_f, OptimizationSystem & /*sys*/) { grad_f.zero(); A_matrix->vector_mult(grad_f, soln); grad_f.add(-1, *F_vector); }
void SumShellMatrix<T>::get_diagonal (NumericVector<T>& dest) const { AutoPtr<NumericVector<T> > a = dest.clone(); dest.zero(); for(numeric_index_type i=matrices.size(); i-->0; ) { matrices[i]->get_diagonal(*a); dest += *a; } }
void AssembleOptimization::gradient (const NumericVector<Number> & soln, NumericVector<Number> & grad_f, OptimizationSystem & /*sys*/) { grad_f.zero(); // Since we've enforced constaints on soln, A and F, // this automatically sets grad_f to zero for constrained // dofs. A_matrix->vector_mult(grad_f, soln); grad_f.add(-1, *F_vector); }
void AssembleOptimization::inequality_constraints (const NumericVector<Number> & X, NumericVector<Number> & C_ineq, OptimizationSystem & /*sys*/) { C_ineq.zero(); std::unique_ptr<NumericVector<Number>> X_localized = NumericVector<Number>::build(X.comm()); X_localized->init(X.size(), false, SERIAL); X.localize(*X_localized); std::vector<Number> constraint_values(1); constraint_values[0] = (*X_localized)(200)*(*X_localized)(200) + (*X_localized)(201) - 5.; for (std::size_t i=0; i<constraint_values.size(); i++) if ((C_ineq.first_local_index() <= i) && (i < C_ineq.last_local_index())) C_ineq.set(i, constraint_values[i]); }
void AssembleOptimization::equality_constraints (const NumericVector<Number> & X, NumericVector<Number> & C_eq, OptimizationSystem & /*sys*/) { C_eq.zero(); UniquePtr<NumericVector<Number> > X_localized = NumericVector<Number>::build(X.comm()); X_localized->init(X.size(), false, SERIAL); X.localize(*X_localized); std::vector<Number> constraint_values(3); constraint_values[0] = (*X_localized)(17); constraint_values[1] = (*X_localized)(23); constraint_values[2] = (*X_localized)(98) + (*X_localized)(185); for (unsigned int i=0; i<constraint_values.size(); i++) if ((C_eq.first_local_index() <= i) && (i < C_eq.last_local_index())) C_eq.set(i, constraint_values[i]); }
void GetSolutionNorm(MultiLevelSolution& mlSol, const unsigned & group, std::vector <double> &data) { int iproc, nprocs; MPI_Comm_rank(MPI_COMM_WORLD, &iproc); MPI_Comm_size(MPI_COMM_WORLD, &nprocs); NumericVector* p2; NumericVector* v2; NumericVector* vol; NumericVector* vol0; p2 = NumericVector::build().release(); v2 = NumericVector::build().release(); vol = NumericVector::build().release(); vol0 = NumericVector::build().release(); if(nprocs == 1) { p2->init(nprocs, 1, false, SERIAL); v2->init(nprocs, 1, false, SERIAL); vol->init(nprocs, 1, false, SERIAL); vol0->init(nprocs, 1, false, SERIAL); } else { p2->init(nprocs, 1, false, PARALLEL); v2->init(nprocs, 1, false, PARALLEL); vol->init(nprocs, 1, false, PARALLEL); vol0->init(nprocs, 1, false, PARALLEL); } p2->zero(); v2->zero(); vol->zero(); vol0->zero(); unsigned level = mlSol._mlMesh->GetNumberOfLevels() - 1; Solution* solution = mlSol.GetSolutionLevel(level); Mesh* msh = mlSol._mlMesh->GetLevel(level); const unsigned dim = msh->GetDimension(); const unsigned max_size = static_cast< unsigned >(ceil(pow(3, dim))); vector< double > solP; vector< vector < double> > solV(dim); vector< vector < double> > x0(dim); vector< vector < double> > x(dim); solP.reserve(max_size); for(unsigned d = 0; d < dim; d++) { solV[d].reserve(max_size); x0[d].reserve(max_size); x[d].reserve(max_size); } double weight; double weight0; vector <double> phiV; vector <double> gradphiV; vector <double> nablaphiV; double *phiP; phiV.reserve(max_size); gradphiV.reserve(max_size * dim); nablaphiV.reserve(max_size * (3 * (dim - 1) + !(dim - 1))); vector < unsigned > solVIndex(dim); solVIndex[0] = mlSol.GetIndex("U"); // get the position of "U" in the ml_sol object solVIndex[1] = mlSol.GetIndex("V"); // get the position of "V" in the ml_sol object if(dim == 3) solVIndex[2] = mlSol.GetIndex("W"); // get the position of "V" in the ml_sol object unsigned solVType = mlSol.GetSolutionType(solVIndex[0]); // get the finite element type for "u" vector < unsigned > solDIndex(dim); solDIndex[0] = mlSol.GetIndex("DX"); // get the position of "U" in the ml_sol object solDIndex[1] = mlSol.GetIndex("DY"); // get the position of "V" in the ml_sol object if(dim == 3) solDIndex[2] = mlSol.GetIndex("DZ"); // get the position of "V" in the ml_sol object unsigned solDType = mlSol.GetSolutionType(solDIndex[0]); unsigned solPIndex; solPIndex = mlSol.GetIndex("PS"); unsigned solPType = mlSol.GetSolutionType(solPIndex); for(int iel = msh->_elementOffset[iproc]; iel < msh->_elementOffset[iproc + 1]; iel++) { if(msh->GetElementGroup(iel) == group) { short unsigned ielt = msh->GetElementType(iel); unsigned ndofV = msh->GetElementDofNumber(iel, solVType); unsigned ndofP = msh->GetElementDofNumber(iel, solPType); unsigned ndofD = msh->GetElementDofNumber(iel, solDType); // resize phiV.resize(ndofV); gradphiV.resize(ndofV * dim); nablaphiV.resize(ndofV * (3 * (dim - 1) + !(dim - 1))); solP.resize(ndofP); for(int d = 0; d < dim; d++) { solV[d].resize(ndofV); x0[d].resize(ndofD); x[d].resize(ndofD); } // get local to global mappings for(unsigned i = 0; i < ndofD; i++) { unsigned idof = msh->GetSolutionDof(i, iel, solDType); for(unsigned d = 0; d < dim; d++) { x0[d][i] = (*msh->_topology->_Sol[d])(idof); x[d][i] = (*msh->_topology->_Sol[d])(idof) + (*solution->_Sol[solDIndex[d]])(idof); } } for(unsigned i = 0; i < ndofV; i++) { unsigned idof = msh->GetSolutionDof(i, iel, solVType); // global to global mapping between solution node and solution dof for(unsigned d = 0; d < dim; d++) { solV[d][i] = (*solution->_Sol[solVIndex[d]])(idof); // global extraction and local storage for the solution } } for(unsigned i = 0; i < ndofP; i++) { unsigned idof = msh->GetSolutionDof(i, iel, solPType); solP[i] = (*solution->_Sol[solPIndex])(idof); } for(unsigned ig = 0; ig < mlSol._mlMesh->_finiteElement[ielt][solVType]->GetGaussPointNumber(); ig++) { // *** get Jacobian and test function and test function derivatives *** msh->_finiteElement[ielt][solVType]->Jacobian(x0, ig, weight0, phiV, gradphiV, nablaphiV); msh->_finiteElement[ielt][solVType]->Jacobian(x, ig, weight, phiV, gradphiV, nablaphiV); phiP = msh->_finiteElement[ielt][solPType]->GetPhi(ig); vol0->add(iproc, weight0); vol->add(iproc, weight); std::vector < double> SolV2(dim, 0.); for(unsigned i = 0; i < ndofV; i++) { for(unsigned d = 0; d < dim; d++) { SolV2[d] += solV[d][i] * phiV[i]; } } double V2 = 0.; for(unsigned d = 0; d < dim; d++) { V2 += SolV2[d] * SolV2[d]; } v2->add(iproc, V2 * weight); double P2 = 0; for(unsigned i = 0; i < ndofP; i++) { P2 += solP[i] * phiP[i]; } P2 *= P2; p2->add(iproc, P2 * weight); } } } p2->close(); v2->close(); vol0->close(); vol->close(); double p2_l2 = p2->l1_norm(); double v2_l2 = v2->l1_norm(); double VOL0 = vol0->l1_norm(); double VOL = vol->l1_norm(); std::cout.precision(14); std::scientific; std::cout << " vol0 = " << VOL0 << std::endl; std::cout << " vol = " << VOL << std::endl; std::cout << " (vol-vol0)/vol0 = " << (VOL - VOL0) / VOL0 << std::endl; std::cout << " p_l2 norm / vol = " << sqrt(p2_l2 / VOL) << std::endl; std::cout << " v_l2 norm / vol = " << sqrt(v2_l2 / VOL) << std::endl; data[1] = (VOL - VOL0) / VOL0; data[2] = VOL; data[3] = sqrt(p2_l2 / VOL); data[4] = sqrt(v2_l2 / VOL); delete p2; delete v2; delete vol; }
void ETD(MultiLevelProblem& ml_prob) { const unsigned& NLayers = NumberOfLayers; adept::Stack& s = FemusInit::_adeptStack; LinearImplicitSystem* mlPdeSys = &ml_prob.get_system<LinearImplicitSystem> ("SW"); // pointer to the linear implicit system named "Poisson" unsigned level = ml_prob._ml_msh->GetNumberOfLevels() - 1u; Mesh* msh = ml_prob._ml_msh->GetLevel(level); // pointer to the mesh (level) object elem* el = msh->el; // pointer to the elem object in msh (level) MultiLevelSolution* mlSol = ml_prob._ml_sol; // pointer to the multilevel solution object Solution* sol = ml_prob._ml_sol->GetSolutionLevel(level); // pointer to the solution (level) object LinearEquationSolver* pdeSys = mlPdeSys->_LinSolver[level]; // pointer to the equation (level) object SparseMatrix* KK = pdeSys->_KK; // pointer to the global stifness matrix object in pdeSys (level) NumericVector* RES = pdeSys->_RES; // pointer to the global residual vector object in pdeSys (level) NumericVector* EPS = pdeSys->_EPS; // pointer to the global residual vector object in pdeSys (level) const unsigned dim = msh->GetDimension(); // get the domain dimension of the problem unsigned iproc = msh->processor_id(); // get the process_id (for parallel computation) unsigned nprocs = msh->n_processors(); // get the process_id (for parallel computation) //solution variable std::vector < unsigned > solIndexh(NLayers); std::vector < unsigned > solPdeIndexh(NLayers); std::vector < unsigned > solIndexv(NLayers); std::vector < unsigned > solPdeIndexv(NLayers); std::vector < unsigned > solIndexHT(NLayers); std::vector < unsigned > solPdeIndexHT(NLayers); std::vector < unsigned > solIndexT(NLayers); vector< int > l2GMap; // local to global mapping for(unsigned i = 0; i < NLayers; i++) { char name[10]; sprintf(name, "h%d", i); solIndexh[i] = mlSol->GetIndex(name); // get the position of "hi" in the sol object solPdeIndexh[i] = mlPdeSys->GetSolPdeIndex(name); // get the position of "hi" in the pdeSys object sprintf(name, "v%d", i); solIndexv[i] = mlSol->GetIndex(name); // get the position of "vi" in the sol object solPdeIndexv[i] = mlPdeSys->GetSolPdeIndex(name); // get the position of "vi" in the pdeSys object sprintf(name, "HT%d", i); solIndexHT[i] = mlSol->GetIndex(name); // get the position of "Ti" in the sol object solPdeIndexHT[i] = mlPdeSys->GetSolPdeIndex(name); // get the position of "Ti" in the pdeSys object sprintf(name, "T%d", i); solIndexT[i] = mlSol->GetIndex(name); // get the position of "Ti" in the sol object } unsigned solTypeh = mlSol->GetSolutionType(solIndexh[0]); // get the finite element type for "hi" unsigned solTypev = mlSol->GetSolutionType(solIndexv[0]); // get the finite element type for "vi" unsigned solTypeHT = mlSol->GetSolutionType(solIndexHT[0]); // get the finite element type for "Ti" vector < double > x; // local coordinates vector< vector < adept::adouble > > solh(NLayers); // local coordinates vector< vector < adept::adouble > > solv(NLayers); // local coordinates vector< vector < adept::adouble > > solHT(NLayers); // local coordinates vector< vector < double > > solT(NLayers); // local coordinates vector< vector < bool > > bdch(NLayers); // local coordinates vector< vector < bool > > bdcv(NLayers); // local coordinates vector< vector < bool > > bdcHT(NLayers); // local coordinates unsigned xType = 2; // get the finite element type for "x", it is always 2 (LAGRANGE QUADRATIC) vector < vector< adept::adouble > > aResh(NLayers); vector < vector< adept::adouble > > aResv(NLayers); vector < vector< adept::adouble > > aResHT(NLayers); KK->zero(); RES->zero(); double maxWaveSpeed = 0.; double dx; for(unsigned k=0; k<NumberOfLayers; k++){ for(unsigned i = msh->_dofOffset[solTypeHT][iproc]; i < msh->_dofOffset[solTypeHT][iproc + 1]; i++){ double valueT = (*sol->_Sol[solIndexT[k]])(i); double valueH = (*sol->_Sol[solIndexh[k]])(i); double valueHT = valueT * valueH; sol->_Sol[solIndexHT[k]]->set(i, valueHT); } sol->_Sol[solIndexHT[k]]->close(); } for(int iel = msh->_elementOffset[iproc]; iel < msh->_elementOffset[iproc + 1]; iel++) { short unsigned ielGeom = msh->GetElementType(iel); unsigned nDofh = msh->GetElementDofNumber(iel, solTypeh); // number of solution element dofs unsigned nDofv = msh->GetElementDofNumber(iel, solTypev); // number of solution element dofs unsigned nDofHT = msh->GetElementDofNumber(iel, solTypeHT); // number of coordinate element dofs unsigned nDofx = msh->GetElementDofNumber(iel, xType); // number of coordinate element dofs unsigned nDofs = nDofh + nDofv + nDofHT; // resize local arrays l2GMap.resize(NLayers * (nDofs) ); for(unsigned i = 0; i < NLayers; i++) { solh[i].resize(nDofh); solv[i].resize(nDofv); solHT[i].resize(nDofHT); solT[i].resize(nDofHT); bdch[i].resize(nDofh); bdcv[i].resize(nDofv); bdcHT[i].resize(nDofHT); aResh[i].resize(nDofh); //resize std::fill(aResh[i].begin(), aResh[i].end(), 0); //set aRes to zero aResv[i].resize(nDofv); //resize std::fill(aResv[i].begin(), aResv[i].end(), 0); //set aRes to zero aResHT[i].resize(nDofHT); //resize std::fill(aResHT[i].begin(), aResHT[i].end(), 0); //set aRes to zero } x.resize(nDofx); //local storage of global mapping and solution for(unsigned i = 0; i < nDofh; i++) { unsigned solDofh = msh->GetSolutionDof(i, iel, solTypeh); // global to global mapping between solution node and solution dof for(unsigned j = 0; j < NLayers; j++) { solh[j][i] = (*sol->_Sol[solIndexh[j]])(solDofh); // global extraction and local storage for the solution bdch[j][i] = ( (*sol->_Bdc[solIndexh[j]])(solDofh) < 1.5) ? true : false; l2GMap[ j * nDofs + i] = pdeSys->GetSystemDof(solIndexh[j], solPdeIndexh[j], i, iel); // global to global mapping between solution node and pdeSys dof } } for(unsigned i = 0; i < nDofv; i++) { unsigned solDofv = msh->GetSolutionDof(i, iel, solTypev); // global to global mapping between solution node and solution dof for(unsigned j = 0; j < NLayers; j++) { solv[j][i] = (*sol->_Sol[solIndexv[j]])(solDofv); // global extraction and local storage for the solution bdcv[j][i] = ( (*sol->_Bdc[solIndexv[j]])(solDofv) < 1.5) ? true : false; l2GMap[ j * nDofs + nDofh + i] = pdeSys->GetSystemDof(solIndexv[j], solPdeIndexv[j], i, iel); // global to global mapping between solution node and pdeSys dof } } for(unsigned i = 0; i < nDofHT; i++) { unsigned solDofHT = msh->GetSolutionDof(i, iel, solTypeHT); // global to global mapping between solution node and solution dof unsigned solDofh = msh->GetSolutionDof(i, iel, solTypeh); for(unsigned j = 0; j < NLayers; j++) { solHT[j][i] = (*sol->_Sol[solIndexHT[j]])(solDofHT); // global extraction and local storage for the solution solT[j][i] = (*sol->_Sol[solIndexT[j]])(solDofHT); // global extraction and local storage for the solution bdcHT[j][i] = ( (*sol->_Bdc[solIndexHT[j]])(solDofHT) < 1.5) ? true : false; l2GMap[ j * nDofs + nDofh + nDofv + i] = pdeSys->GetSystemDof(solIndexHT[j], solPdeIndexHT[j], i, iel); // global to global mapping between solution node and pdeSys dof //std::cout << solT[j][i] << " "; } } s.new_recording(); for(unsigned i = 0; i < nDofx; i++) { unsigned xDof = msh->GetSolutionDof(i, iel, xType); // global to global mapping between coordinates node and coordinate dof x[i] = (*msh->_topology->_Sol[0])(xDof); // global extraction and local storage for the element coordinates } double xmid = 0.5 * (x[0] + x[1]); //std::cout << xmid << std::endl; double zz = sqrt(aa * aa - xmid * xmid); // z coordinate of points on sphere double dd = aa * acos((zz * z_c) / (aa * aa)); // distance to center point on sphere [m] double hh = 1 - dd * dd / (bb * bb); double b = ( H_shelf + H_0 / 2 * (1 + tanh(hh / phi)) ); double hTot = 0.; double beta = 0.2; std::vector < adept::adouble > P(NLayers); for(unsigned k = 0; k < NLayers; k++) { hTot += solh[k][0].value(); adept::adouble rhok = rho1[k] - beta * solT[k][0]; P[k] = - rhok * 9.81 * b; // bottom topography for( unsigned j = 0; j < NLayers; j++){ adept::adouble rhoj = (j <= k) ? (rho1[j] - beta * solT[j][0]) : rhok; P[k] += rhoj * 9.81 * solh[j][0]; } P[k] /= 1024; } std::vector < double > hALE(NLayers, 0.); hALE[0] = hRest[0] + (hTot - b); for(unsigned k = 1; k < NLayers - 1; k++){ hALE[k] = hRest[k]; } hALE[NLayers - 1] = b - hRest[NLayers - 1]; std::vector < double > w(NLayers+1, 0.); dx = x[1] - x[0]; for(unsigned k = NLayers; k>1; k--){ w[k-1] = w[k] - solh[k-1][0].value() * (solv[k-1][1].value() - solv[k-1][0].value() )/dx- ( hALE[k-1] - solh[k-1][0].value()) / dt; //std::cout << hALE[k-1] << " " << w[k-1] << " "; } //std::cout<<std::endl; std::vector < adept::adouble > zMid(NLayers); for(unsigned k = 0; k < NLayers; k++) { zMid[k] = -b + solh[k][0]/2; for(unsigned i = k+1; i < NLayers; i++) { zMid[k] += solh[i][0]; } } double celerity = sqrt( 9.81 * hTot); for(unsigned i = 0; i<NLayers; i++){ double vmid = 0.5 * ( solv[i][0].value() + solv[i][1].value() ); maxWaveSpeed = ( maxWaveSpeed > fabs(vmid) + fabs(celerity) )? maxWaveSpeed : fabs(vmid) + fabs(celerity); } for(unsigned k = 0; k < NLayers; k++) { if(!bdch[k][0]) { for (unsigned j = 0; j < nDofv; j++) { double sign = ( j == 0) ? 1. : -1; aResh[k][0] += sign * solh[k][0] * solv[k][j] / dx; } aResh[k][0] += w[k+1] - w[k]; } adept::adouble vMid = 0.5 * (solv[k][0] + solv[k][1]); adept::adouble fv = 0.5 * vMid * vMid + P[k]; for (unsigned i = 0; i < nDofv; i++) { if(!bdcv[k][i]) { double sign = ( i == 0) ? -1. : 1; aResv[k][i] += sign * fv / dx; if ( k > 0 ){ aResv[k][i] -= 0.5 * ( w[k] * 0.5 * ( solv[k-1][i] - solv[k][i] ) / (0.5 * ( solh[k-1][0] + solh[k][0] ) ) ); } if (k < NLayers - 1) { aResv[k][i] -= 0.5 * ( w[k+1] * 0.5 * ( solv[k][i] - solv[k+1][i] ) / (0.5 * ( solh[k][0] + solh[k+1][0] ) ) ); } //aResv[k][i] += sign * 9.81 * rho1[k] / 1024. * zMid[k] / dx; } } if(!bdcHT[k][0]) { for (unsigned j = 0; j < nDofv; j++) { double sign = ( j == 0) ? 1. : -1; aResHT[k][0] += sign * solv[k][j] * solHT[k][0] / dx; } if(k<NLayers-1){ aResHT[k][0] += w[k+1] * 0.5 * (solHT[k][0]/solh[k][0] + solHT[k+1][0]/solh[k+1][0]); //aResHT[k][0] += w[k+1] * 0.5 * (solT[k][0] + solT[k+1][0]); } if( k > 0){ aResHT[k][0] -= w[k] * 0.5 * (solHT[k-1][0]/solh[k-1][0] + solHT[k][0]/solh[k][0] ); //aResHT[k][0] -= w[k] * 0.5 * (solT[k-1][0] + solT[k][0]); } } } vector< double > Res(NLayers * nDofs); // local redidual vector unsigned counter = 0; for(unsigned k = 0; k < NLayers; k++) { for(int i = 0; i < nDofh; i++) { Res[counter] = aResh[k][i].value(); counter++; } for(int i = 0; i < nDofv; i++) { Res[counter] = aResv[k][i].value(); counter++; } for(int i = 0; i < nDofHT; i++) { Res[counter] = aResHT[k][i].value(); counter++; } } RES->add_vector_blocked(Res, l2GMap); for(unsigned k = 0; k < NLayers; k++) { // define the dependent variables s.dependent(&aResh[k][0], nDofh); s.dependent(&aResv[k][0], nDofv); s.dependent(&aResHT[k][0], nDofHT); // define the independent variables s.independent(&solh[k][0], nDofh); s.independent(&solv[k][0], nDofv); s.independent(&solHT[k][0], nDofHT); } // get the jacobian matrix (ordered by row major ) vector < double > Jac(NLayers * nDofs * NLayers * nDofs); s.jacobian(&Jac[0], true); //store K in the global matrix KK KK->add_matrix_blocked(Jac, l2GMap, l2GMap); s.clear_independents(); s.clear_dependents(); } RES->close(); KK->close(); // PetscViewer viewer; // PetscViewerDrawOpen(PETSC_COMM_WORLD,NULL,NULL,0,0,900,900,&viewer); // PetscObjectSetName((PetscObject)viewer,"FSI matrix"); // PetscViewerPushFormat(viewer,PETSC_VIEWER_DRAW_LG); // MatView((static_cast<PetscMatrix*>(KK))->mat(),viewer); // double a; // std::cin>>a; // // abort(); MFN mfn; Mat A = (static_cast<PetscMatrix*>(KK))->mat(); FN f, f1, f2, f3 , f4; std::cout << "dt = " << dt << " dx = "<< dx << " maxWaveSpeed = "<<maxWaveSpeed << std::endl; //dt = 100.; Vec v = (static_cast< PetscVector* >(RES))->vec(); Vec y = (static_cast< PetscVector* >(EPS))->vec(); MFNCreate( PETSC_COMM_WORLD, &mfn ); MFNSetOperator( mfn, A ); MFNGetFN( mfn, &f ); // FNCreate(PETSC_COMM_WORLD, &f1); // FNCreate(PETSC_COMM_WORLD, &f2); // FNCreate(PETSC_COMM_WORLD, &f3); // FNCreate(PETSC_COMM_WORLD, &f4); // // FNSetType(f1, FNEXP); // // FNSetType(f2, FNRATIONAL); // double coeff1[1] = { -1}; // FNRationalSetNumerator(f2, 1, coeff1); // FNRationalSetDenominator(f2, 0, PETSC_NULL); // // FNSetType( f3, FNCOMBINE ); // // FNCombineSetChildren(f3, FN_COMBINE_ADD, f1, f2); // // FNSetType(f4, FNRATIONAL); // double coeff2[2] = {1., 0.}; // FNRationalSetNumerator(f4, 2, coeff2); // FNRationalSetDenominator(f4, 0, PETSC_NULL); // // FNSetType( f, FNCOMBINE ); // // FNCombineSetChildren(f, FN_COMBINE_DIVIDE, f3, f4); FNPhiSetIndex(f,1); FNSetType( f, FNPHI ); // FNView(f,PETSC_VIEWER_STDOUT_WORLD); FNSetScale( f, dt, dt); MFNSetFromOptions( mfn ); MFNSolve( mfn, v, y); MFNDestroy( &mfn ); // FNDestroy(&f1); // FNDestroy(&f2); // FNDestroy(&f3); // FNDestroy(&f4); sol->UpdateSol(mlPdeSys->GetSolPdeIndex(), EPS, pdeSys->KKoffset); unsigned solIndexeta = mlSol->GetIndex("eta"); unsigned solIndexb = mlSol->GetIndex("b"); sol->_Sol[solIndexeta]->zero(); for(unsigned k=0;k<NumberOfLayers;k++){ sol->_Sol[solIndexeta]->add(*sol->_Sol[solIndexh[k]]); } sol->_Sol[solIndexeta]->add(-1,*sol->_Sol[solIndexb]); for(unsigned k=0; k<NumberOfLayers; k++){ for(unsigned i = msh->_dofOffset[solTypeHT][iproc]; i < msh->_dofOffset[solTypeHT][iproc + 1]; i++){ double valueHT = (*sol->_Sol[solIndexHT[k]])(i); double valueH = (*sol->_Sol[solIndexh[k]])(i); double valueT = valueHT/valueH; sol->_Sol[solIndexT[k]]->set(i, valueT); } sol->_Sol[solIndexT[k]]->close(); } }
void SparseMatrix<T>::vector_mult (NumericVector<T>& dest, const NumericVector<T>& arg) const { dest.zero(); this->vector_mult_add(dest,arg); }
void AssembleProblem(MultiLevelProblem& ml_prob) { // ************** J dx = f - J x_old ****************** // level is the level of the PDE system to be assembled // levelMax is the Maximum level of the MultiLevelProblem // assembleMatrix is a flag that tells if only the residual or also the matrix should be assembled NonLinearImplicitSystemWithPrimalDualActiveSetMethod* mlPdeSys = &ml_prob.get_system<NonLinearImplicitSystemWithPrimalDualActiveSetMethod> ("OptSys"); const unsigned level = mlPdeSys->GetLevelToAssemble(); const bool assembleMatrix = mlPdeSys->GetAssembleMatrix(); Mesh* msh = ml_prob._ml_msh->GetLevel(level); MultiLevelSolution* ml_sol = ml_prob._ml_sol; Solution* sol = ml_prob._ml_sol->GetSolutionLevel(level); LinearEquationSolver* pdeSys = mlPdeSys->_LinSolver[level]; SparseMatrix* KK = pdeSys->_KK; NumericVector* RES = pdeSys->_RES; const unsigned dim = msh->GetDimension(); // get the domain dimension of the problem const unsigned dim2 = (3 * (dim - 1) + !(dim - 1)); // dim2 is the number of second order partial derivatives (1,3,6 depending on the dimension) const unsigned max_size = static_cast< unsigned >(ceil(pow(3, dim))); // conservative: based on line3, quad9, hex27 const unsigned iproc = msh->processor_id(); //************** geometry (at dofs) ************************************* vector < vector < double > > coords_at_dofs(dim); vector < unsigned int > SolFEType_domain(dim); for (unsigned d = 0; d < dim; d++) SolFEType_domain[d] = BIQUADR_FE; for (unsigned i = 0; i < coords_at_dofs.size(); i++) coords_at_dofs[i].reserve(max_size); //************** geometry (at quadrature points) ************************************* vector < double > coord_at_qp(dim); //************** geometry phi ************************** vector < vector < double > > phi_fe_qp_domain(dim); vector < vector < double > > phi_x_fe_qp_domain(dim); vector < vector < double > > phi_xx_fe_qp_domain(dim); for(int fe = 0; fe < dim; fe++) { phi_fe_qp_domain[fe].reserve(max_size); phi_x_fe_qp_domain[fe].reserve(max_size * dim); phi_xx_fe_qp_domain[fe].reserve(max_size * dim2); } //*************************************************** //********* WHOLE SET OF VARIABLES ****************** //*************************************************** const unsigned int n_unknowns = mlPdeSys->GetSolPdeIndex().size(); enum Sol_pos{pos_state = 0, pos_ctrl, pos_adj, pos_mu}; //these are known at compile-time //right now this is the same as Sol_pos = SolPdeIndex, but now I want to have flexible rows and columns // the ROW index corresponds to the EQUATION we want to solve // the COLUMN index corresponds to the column variables // Now, first of all we have to make sure that the Sparsity pattern is correctly built... // This means that we should write the Sparsity pattern with COLUMNS independent of ROWS! // But that implies that the BOUNDARY CONDITIONS will be enforced in OFF-DIAGONAL BLOCKS! // In fact, having the row order be different from the column order implies that the diagonal blocks would be RECTANGULAR. // Although this is in principle possible, I would avoid doing that for now. // const unsigned int pos_state = mlPdeSys->GetSolPdeIndex("state"); //these are known at run-time, so they are slower // const unsigned int pos_ctrl = mlPdeSys->GetSolPdeIndex("control"); //these are known at run-time, so they are slower // const unsigned int pos_adj = mlPdeSys->GetSolPdeIndex("adjoint"); //these are known at run-time, so they are slower // const unsigned int pos_mu = mlPdeSys->GetSolPdeIndex("mu"); //these are known at run-time, so they are slower assert(pos_state == mlPdeSys->GetSolPdeIndex("state")); assert(pos_ctrl == mlPdeSys->GetSolPdeIndex("control")); assert(pos_adj == mlPdeSys->GetSolPdeIndex("adjoint")); assert(pos_mu == mlPdeSys->GetSolPdeIndex("mu")); //*************************************************** const int solFEType_max = BIQUADR_FE; //biquadratic vector < std::string > Solname(n_unknowns); Solname[pos_state] = "state"; Solname[pos_ctrl] = "control"; Solname[pos_adj] = "adjoint"; Solname[pos_mu] = "mu"; //*************************************************** vector < unsigned int > SolPdeIndex(n_unknowns); //index as in the row/column of the matrix (diagonal blocks are square) vector < unsigned int > SolIndex(n_unknowns); //index as in the MultilevelSolution vector vector < unsigned int > SolFEType(n_unknowns); //FEtype of each MultilevelSolution vector < unsigned int > Sol_n_el_dofs(n_unknowns); //number of element dofs std::fill(Sol_n_el_dofs.begin(), Sol_n_el_dofs.end(), 0); for(unsigned ivar=0; ivar < n_unknowns; ivar++) { SolPdeIndex[ivar] = mlPdeSys->GetSolPdeIndex( Solname[ivar].c_str() ); assert(ivar == SolPdeIndex[ivar]); SolIndex[ivar] = ml_sol->GetIndex ( Solname[ivar].c_str() ); SolFEType[ivar] = ml_sol->GetSolutionType ( SolIndex[ivar]); } //************* shape functions (at dofs and quadrature points) ************************************** double weight_qp; vector < vector < double > > phi_fe_qp(n_unknowns); vector < vector < double > > phi_x_fe_qp(n_unknowns); vector < vector < double > > phi_xx_fe_qp(n_unknowns); vector < vector < vector < double > > > phi_x_fe_qp_vec(n_unknowns); for(int fe = 0; fe < n_unknowns; fe++) { phi_fe_qp[fe].reserve(max_size); phi_x_fe_qp[fe].reserve(max_size * dim); phi_xx_fe_qp[fe].reserve(max_size * dim2); phi_x_fe_qp_vec[fe].resize(dim); for(int d = 0; d < dim; d++) { phi_x_fe_qp_vec[fe][d].reserve(max_size); } } //----------- quantities (at dof objects) ------------------------------ vector < vector < double > > sol_eldofs(n_unknowns); for(int k=0; k<n_unknowns; k++) sol_eldofs[k].reserve(max_size); //************** act flag (at dof objects) **************************** std::string act_flag_name = "act_flag"; unsigned int solIndex_act_flag = ml_sol->GetIndex(act_flag_name.c_str()); unsigned int solFEType_act_flag = ml_sol->GetSolutionType(solIndex_act_flag); if(sol->GetSolutionTimeOrder(solIndex_act_flag) == 2) { *(sol->_SolOld[solIndex_act_flag]) = *(sol->_Sol[solIndex_act_flag]); } //********* variables for ineq constraints (at dof objects) ***************** const int ineq_flag = INEQ_FLAG; const double c_compl = C_COMPL; vector < double/*int*/ > sol_actflag; sol_actflag.reserve(max_size); //flag for active set vector < double > ctrl_lower; ctrl_lower.reserve(max_size); vector < double > ctrl_upper; ctrl_upper.reserve(max_size); //------------ quantities (at quadrature points) --------------------- vector<double> sol_qp(n_unknowns); vector< vector<double> > sol_grad_qp(n_unknowns); std::fill(sol_qp.begin(), sol_qp.end(), 0.); for (unsigned k = 0; k < n_unknowns; k++) { sol_grad_qp[k].resize(dim); std::fill(sol_grad_qp[k].begin(), sol_grad_qp[k].end(), 0.); } //******* EQUATION RELATED STUFF ******************************************** int m_b_f[n_unknowns][n_unknowns]; m_b_f[pos_state][pos_state] = 1; //nonzero m_b_f[pos_state][pos_ctrl] = 0; //THIS IS ZERO IN NON-LIFTING APPROACHES (there are also pieces that go on top on blocks that are already meant to be different from zero) m_b_f[pos_state][pos_adj] = 1; //nonzero m_b_f[pos_state][pos_mu] = 0; //this is zero without state constraints m_b_f[pos_ctrl][pos_state] = 0;//THIS IS ZERO IN NON-LIFTING APPROACHES m_b_f[pos_ctrl][pos_ctrl] = 1;//nonzero m_b_f[pos_ctrl][pos_adj] = 1;//nonzero m_b_f[pos_ctrl][pos_mu] = 1;//nonzero m_b_f[pos_adj][pos_state] = 1; //nonzero m_b_f[pos_adj][pos_ctrl] = 1; //nonzero m_b_f[pos_adj][pos_adj] = 0; //this must always be zero m_b_f[pos_adj][pos_mu] = 0; //this must always be zero m_b_f[pos_mu][pos_state] = 0; //this is zero without state constraints m_b_f[pos_mu][pos_ctrl] = 1; //nonzero m_b_f[pos_mu][pos_adj] = 0; //this must always be zero m_b_f[pos_mu][pos_mu] = 1; //nonzero //*************************************************** vector < vector < int > > L2G_dofmap(n_unknowns); for(int i = 0; i < n_unknowns; i++) { L2G_dofmap[i].reserve(max_size); } vector< int > L2G_dofmap_AllVars; L2G_dofmap_AllVars.reserve( n_unknowns*max_size ); vector< double > Res; Res.reserve( n_unknowns*max_size ); vector< double > Jac; Jac.reserve( n_unknowns*max_size * n_unknowns*max_size); //*************************************************** //********************* DATA ************************ double alpha = ALPHA_CTRL_VOL; double beta = BETA_CTRL_VOL; double penalty_strong = 10e+14; //*************************************************** RES->zero(); if (assembleMatrix) KK->zero(); // element loop: each process loops only on the elements that it owns for (int iel = msh->_elementOffset[iproc]; iel < msh->_elementOffset[iproc + 1]; iel++) { short unsigned ielGeom = msh->GetElementType(iel); // element geometry type //******************** GEOMETRY ********************* for (unsigned jdim = 0; jdim < dim; jdim++) { unsigned nDofx = msh->GetElementDofNumber(iel, SolFEType_domain[jdim]); coords_at_dofs[jdim].resize(nDofx); // local storage of coordinates for (unsigned i = 0; i < coords_at_dofs[jdim].size(); i++) { unsigned xDof = msh->GetSolutionDof(i, iel, SolFEType_domain[jdim]); // global to global mapping between coordinates node and coordinate dof coords_at_dofs[jdim][i] = (*msh->_topology->_Sol[jdim])(xDof); // global extraction and local storage for the element coordinates } } // elem average point vector < double > elem_center(dim); for (unsigned j = 0; j < dim; j++) { elem_center[j] = 0.; } for (unsigned j = 0; j < dim; j++) { for (unsigned i = 0; i < coords_at_dofs[j].size(); i++) { elem_center[j] += coords_at_dofs[j][i]; } } for (unsigned j = 0; j < dim; j++) { elem_center[j] = elem_center[j]/coords_at_dofs[j].size(); } //*************************************************** //****** set target domain flag ********************* int target_flag = 0; target_flag = ElementTargetFlag(elem_center); //*************************************************** //all vars################################################################### for (unsigned k = 0; k < n_unknowns; k++) { unsigned ndofs_unk = msh->GetElementDofNumber(iel, SolFEType[k]); Sol_n_el_dofs[k] = ndofs_unk; sol_eldofs[k].resize(ndofs_unk); L2G_dofmap[k].resize(ndofs_unk); for (unsigned i = 0; i < ndofs_unk; i++) { unsigned solDof = msh->GetSolutionDof(i, iel, SolFEType[k]); // global to global mapping between solution node and solution dof // via local to global solution node sol_eldofs[k][i] = (*sol->_Sol[SolIndex[k]])(solDof); // global extraction and local storage for the solution L2G_dofmap[k][i] = pdeSys->GetSystemDof(SolIndex[k], SolPdeIndex[k], i, iel); // global to global mapping between solution node and pdeSys dof } } //all vars################################################################### for (unsigned k = 0; k < n_unknowns; k++) { for(int d = 0; d < dim; d++) { phi_x_fe_qp_vec[k][d].resize(Sol_n_el_dofs[k]); } } //************** update active set flag for current nonlinear iteration **************************** // 0: inactive; 1: active_a; 2: active_b assert(Sol_n_el_dofs[pos_mu] == Sol_n_el_dofs[pos_ctrl]); sol_actflag.resize(Sol_n_el_dofs[pos_mu]); ctrl_lower.resize(Sol_n_el_dofs[pos_mu]); ctrl_upper.resize(Sol_n_el_dofs[pos_mu]); std::fill(sol_actflag.begin(), sol_actflag.end(), 0); std::fill(ctrl_lower.begin(), ctrl_lower.end(), 0.); std::fill(ctrl_upper.begin(), ctrl_upper.end(), 0.); for (unsigned i = 0; i < sol_actflag.size(); i++) { std::vector<double> node_coords_i(dim,0.); for (unsigned d = 0; d < dim; d++) node_coords_i[d] = coords_at_dofs[d][i]; ctrl_lower[i] = InequalityConstraint(node_coords_i,false); ctrl_upper[i] = InequalityConstraint(node_coords_i,true); if ( (sol_eldofs[pos_mu][i] + c_compl * (sol_eldofs[pos_ctrl][i] - ctrl_lower[i] )) < 0 ) sol_actflag[i] = 1; else if ( (sol_eldofs[pos_mu][i] + c_compl * (sol_eldofs[pos_ctrl][i] - ctrl_upper[i] )) > 0 ) sol_actflag[i] = 2; } //************** act flag **************************** unsigned nDof_act_flag = msh->GetElementDofNumber(iel, solFEType_act_flag); // number of solution element dofs for (unsigned i = 0; i < nDof_act_flag; i++) { unsigned solDof_mu = msh->GetSolutionDof(i, iel, solFEType_act_flag); (sol->_Sol[solIndex_act_flag])->set(solDof_mu,sol_actflag[i]); } //******************** ALL VARS ********************* unsigned nDof_AllVars = 0; for (unsigned k = 0; k < n_unknowns; k++) { nDof_AllVars += Sol_n_el_dofs[k]; } // TODO COMPUTE MAXIMUM maximum number of element dofs for one scalar variable int nDof_max = 0; for (unsigned k = 0; k < n_unknowns; k++) { if(Sol_n_el_dofs[k] > nDof_max) nDof_max = Sol_n_el_dofs[k]; } Res.resize(nDof_AllVars); std::fill(Res.begin(), Res.end(), 0.); Jac.resize(nDof_AllVars * nDof_AllVars); std::fill(Jac.begin(), Jac.end(), 0.); L2G_dofmap_AllVars.resize(0); for (unsigned k = 0; k < n_unknowns; k++) L2G_dofmap_AllVars.insert(L2G_dofmap_AllVars.end(),L2G_dofmap[k].begin(),L2G_dofmap[k].end()); //*************************************************** //***** set control flag **************************** int control_el_flag = 0; control_el_flag = ControlDomainFlag_internal_restriction(elem_center); std::vector<int> control_node_flag(Sol_n_el_dofs[pos_ctrl],0); if (control_el_flag == 1) std::fill(control_node_flag.begin(), control_node_flag.end(), 1); //*************************************************** // *** Gauss point loop *** for (unsigned ig = 0; ig < msh->_finiteElement[ielGeom][solFEType_max]->GetGaussPointNumber(); ig++) { // *** get gauss point weight, test function and test function partial derivatives *** for(unsigned int k = 0; k < n_unknowns; k++) { msh->_finiteElement[ielGeom][SolFEType[k]]->Jacobian(coords_at_dofs, ig, weight_qp, phi_fe_qp[k], phi_x_fe_qp[k], phi_xx_fe_qp[k]); } for (unsigned k = 0; k < n_unknowns; k++) { for(unsigned int d = 0; d < dim; d++) { for(unsigned int i = 0; i < Sol_n_el_dofs[k]; i++) { phi_x_fe_qp_vec[k][d][i] = phi_x_fe_qp[k][i * dim + d]; } } } //HAVE TO RECALL IT TO HAVE BIQUADRATIC JACOBIAN for (unsigned int d = 0; d < dim; d++) { msh->_finiteElement[ielGeom][SolFEType_domain[d]]->Jacobian(coords_at_dofs, ig, weight_qp, phi_fe_qp_domain[d], phi_x_fe_qp_domain[d], phi_xx_fe_qp_domain[d]); } //========= fill gauss value xyz ================== std::fill(coord_at_qp.begin(), coord_at_qp.end(), 0.); for (unsigned d = 0; d < dim; d++) { for (unsigned i = 0; i < coords_at_dofs[d].size(); i++) { coord_at_qp[d] += coords_at_dofs[d][i] * phi_fe_qp_domain[d][i]; } } //========= fill gauss value xyz ================== //========= fill gauss value quantities ================== std::fill(sol_qp.begin(), sol_qp.end(), 0.); for (unsigned k = 0; k < n_unknowns; k++) { std::fill(sol_grad_qp[k].begin(), sol_grad_qp[k].end(), 0.); } for (unsigned k = 0; k < n_unknowns; k++) { for (unsigned i = 0; i < Sol_n_el_dofs[k]; i++) { sol_qp[k] += sol_eldofs[k][i] * phi_fe_qp[k][i]; for (unsigned d = 0; d < dim; d++) sol_grad_qp[k][d] += sol_eldofs[k][i] * phi_x_fe_qp[k][i * dim + d]; } } //========= fill gauss value quantities ================== //==========FILLING THE EQUATIONS =========== for (unsigned i = 0; i < nDof_max; i++) { //======================Residuals======================= // =============== Res[ assemble_jacobian<double,double>::res_row_index(Sol_n_el_dofs,pos_state,i) ] += - weight_qp * (target_flag * phi_fe_qp[pos_state][i] * ( m_b_f[pos_state][pos_state] * sol_qp[pos_state] - DesiredTarget(coord_at_qp) ) + m_b_f[pos_state][pos_adj] * ( assemble_jacobian<double,double>::laplacian_row(phi_x_fe_qp_vec, sol_grad_qp, pos_state, pos_adj, i, dim) - sol_qp[pos_adj] * nonlin_term_derivative(phi_fe_qp[pos_state][i]) * sol_qp[pos_ctrl]) ); // ============== if ( control_el_flag == 1) Res[ assemble_jacobian<double,double>::res_row_index(Sol_n_el_dofs,pos_ctrl,i) ] += /*(control_node_flag[i]) **/ - weight_qp * ( + m_b_f[pos_ctrl][pos_ctrl] * alpha * phi_fe_qp[pos_ctrl][i] * sol_qp[pos_ctrl] + m_b_f[pos_ctrl][pos_ctrl] * beta * assemble_jacobian<double,double>::laplacian_row(phi_x_fe_qp_vec, sol_grad_qp, pos_ctrl, pos_ctrl, i, dim) - m_b_f[pos_ctrl][pos_adj] * phi_fe_qp[pos_ctrl][i] * sol_qp[pos_adj] * nonlin_term_function(sol_qp[pos_state]) ); else if ( control_el_flag == 0) Res[ assemble_jacobian<double,double>::res_row_index(Sol_n_el_dofs,pos_ctrl,i) ] += /*(1 - control_node_flag[i]) **/ m_b_f[pos_ctrl][pos_ctrl] * (- penalty_strong) * (sol_eldofs[pos_ctrl][i]); // ============= Res[ assemble_jacobian<double,double>::res_row_index(Sol_n_el_dofs,pos_adj,i) ] += - weight_qp * ( + m_b_f[pos_adj][pos_state] * assemble_jacobian<double,double>::laplacian_row(phi_x_fe_qp_vec, sol_grad_qp, pos_adj, pos_state, i, dim) - m_b_f[pos_adj][pos_ctrl] * phi_fe_qp[pos_adj][i] * sol_qp[pos_ctrl] * nonlin_term_function(sol_qp[pos_state]) ); //======================End Residuals======================= if (assembleMatrix) { // *** phi_j loop *** for (unsigned j = 0; j < nDof_max; j++) { //============ delta_state row ============================ Jac[ assemble_jacobian<double,double>::jac_row_col_index(Sol_n_el_dofs, nDof_AllVars, pos_state, pos_state, i, j) ] += m_b_f[pos_state][pos_state] * weight_qp * target_flag * phi_fe_qp[pos_state][j] * phi_fe_qp[pos_state][i]; Jac[ assemble_jacobian<double,double>::jac_row_col_index(Sol_n_el_dofs, nDof_AllVars, pos_state, pos_adj, i, j) ] += m_b_f[pos_state][pos_adj] * weight_qp * ( assemble_jacobian<double,double>::laplacian_row_col(phi_x_fe_qp_vec,phi_x_fe_qp_vec, pos_state, pos_adj, i, j, dim) - phi_fe_qp[pos_adj][j] * nonlin_term_derivative(phi_fe_qp[pos_state][i]) * sol_qp[pos_ctrl] ); //=========== delta_control row =========================== if ( control_el_flag == 1) { Jac[ assemble_jacobian<double,double>::jac_row_col_index(Sol_n_el_dofs, nDof_AllVars, pos_ctrl, pos_ctrl, i, j) ] += m_b_f[pos_ctrl][pos_ctrl] * ( control_node_flag[i]) * weight_qp * ( beta * control_el_flag * assemble_jacobian<double,double>::laplacian_row_col(phi_x_fe_qp_vec,phi_x_fe_qp_vec, pos_ctrl, pos_ctrl, i, j, dim) + alpha * control_el_flag * phi_fe_qp[pos_ctrl][i] * phi_fe_qp[pos_ctrl][j] ); Jac[ assemble_jacobian<double,double>::jac_row_col_index(Sol_n_el_dofs, nDof_AllVars, pos_ctrl, pos_adj, i, j) ] += m_b_f[pos_ctrl][pos_adj] * control_node_flag[i] * weight_qp * ( - phi_fe_qp[pos_ctrl][i] * phi_fe_qp[pos_adj][j] * nonlin_term_function(sol_qp[pos_state]) ); } else if ( control_el_flag == 0 && i == j) { Jac[ assemble_jacobian<double,double>::jac_row_col_index(Sol_n_el_dofs, nDof_AllVars, pos_ctrl, pos_ctrl, i, j) ] += m_b_f[pos_ctrl][pos_ctrl] * (1 - control_node_flag[i]) * penalty_strong; } //=========== delta_adjoint row =========================== Jac[ assemble_jacobian<double,double>::jac_row_col_index(Sol_n_el_dofs, nDof_AllVars, pos_adj, pos_state, i, j) ] += m_b_f[pos_adj][pos_state] * weight_qp * ( assemble_jacobian<double,double>::laplacian_row_col(phi_x_fe_qp_vec,phi_x_fe_qp_vec, pos_adj, pos_state, i, j, dim) - phi_fe_qp[pos_adj][i] * nonlin_term_derivative(phi_fe_qp[pos_state][j]) * sol_qp[pos_ctrl] ); Jac[ assemble_jacobian<double,double>::jac_row_col_index(Sol_n_el_dofs, nDof_AllVars, pos_adj, pos_ctrl, i, j) ] += m_b_f[pos_adj][pos_ctrl] * weight_qp * ( - phi_fe_qp[pos_adj][i] * phi_fe_qp[pos_ctrl][j] * nonlin_term_function(sol_qp[pos_state]) ); } // end phi_j loop } // endif assemble_matrix } // end phi_i loop } // end gauss point loop //std::vector<double> Res_ctrl (Sol_n_el_dofs[pos_ctrl]); std::fill(Res_ctrl.begin(),Res_ctrl.end(), 0.); for (unsigned i = 0; i < sol_eldofs[pos_ctrl].size(); i++) { unsigned n_els_that_node = 1; if ( control_el_flag == 1) { // Res[Sol_n_el_dofs[pos_state] + i] += - ( + n_els_that_node * ineq_flag * sol_eldofs[pos_mu][i] /*- ( 0.4 + sin(M_PI * x[0][i]) * sin(M_PI * x[1][i]) )*/ ); // Res_ctrl[i] = Res[Sol_n_el_dofs[pos_state] + i]; } } //========== end of integral-based part RES->add_vector_blocked(Res, L2G_dofmap_AllVars); if (assembleMatrix) KK->add_matrix_blocked(Jac, L2G_dofmap_AllVars, L2G_dofmap_AllVars); //========== dof-based part, without summation //============= delta_mu row =============================== std::vector<double> Res_mu (Sol_n_el_dofs[pos_mu]); std::fill(Res_mu.begin(),Res_mu.end(), 0.); for (unsigned i = 0; i < sol_actflag.size(); i++) { if (sol_actflag[i] == 0) { //inactive Res_mu [i] = (- ineq_flag) * ( 1. * sol_eldofs[pos_mu][i] ); // Res_mu [i] = Res[res_row_index(Sol_n_el_dofs,pos_mu,i)]; } else if (sol_actflag[i] == 1) { //active_a Res_mu [i] = (- ineq_flag) * c_compl * ( sol_eldofs[pos_ctrl][i] - ctrl_lower[i]); } else if (sol_actflag[i] == 2) { //active_b Res_mu [i] = (- ineq_flag) * c_compl * ( sol_eldofs[pos_ctrl][i] - ctrl_upper[i]); } } RES->insert(Res_mu, L2G_dofmap[pos_mu]); //============= delta_ctrl - mu =============================== KK->matrix_set_off_diagonal_values_blocked(L2G_dofmap[pos_ctrl], L2G_dofmap[pos_mu], m_b_f[pos_ctrl][pos_mu] * ineq_flag * 1.); //============= delta_mu - ctrl row =============================== for (unsigned i = 0; i < sol_actflag.size(); i++) if (sol_actflag[i] != 0 ) sol_actflag[i] = m_b_f[pos_mu][pos_ctrl] * ineq_flag * c_compl; KK->matrix_set_off_diagonal_values_blocked(L2G_dofmap[pos_mu], L2G_dofmap[pos_ctrl], sol_actflag); //============= delta_mu - mu row =============================== for (unsigned i = 0; i < sol_actflag.size(); i++) sol_actflag[i] = m_b_f[pos_mu][pos_mu] * ( ineq_flag * (1 - sol_actflag[i]/c_compl) + (1-ineq_flag) * 1. ); //can do better to avoid division, maybe use modulo operator KK->matrix_set_off_diagonal_values_blocked(L2G_dofmap[pos_mu], L2G_dofmap[pos_mu], sol_actflag ); } //end element loop for each process RES->close(); if (assembleMatrix) KK->close(); // std::ostringstream mat_out; mat_out << ml_prob.GetFilesHandler()->GetOutputPath() << "/" << "jacobian" << mlPdeSys->GetNonlinearIt() << ".txt"; // KK->print_matlab(mat_out.str(),"ascii"); // KK->print(); // ***************** END ASSEMBLY ******************* unsigned int global_ctrl_size = pdeSys->KKoffset[pos_ctrl+1][iproc] - pdeSys->KKoffset[pos_ctrl][iproc]; std::vector<double> one_times_mu(global_ctrl_size, 0.); std::vector<int> positions(global_ctrl_size); // double position_mu_i; for (unsigned i = 0; i < positions.size(); i++) { positions[i] = pdeSys->KKoffset[pos_ctrl][iproc] + i; // position_mu_i = pdeSys->KKoffset[pos_mu][iproc] + i; // std::cout << position_mu_i << std::endl; one_times_mu[i] = m_b_f[pos_ctrl][pos_mu] * ineq_flag * 1. * (*sol->_Sol[SolIndex[pos_mu]])(i/*position_mu_i*/) ; } RES->add_vector_blocked(one_times_mu, positions); // RES->print(); return; }
// Here we compute the residual R(x) = K(x)*x - f. The current solution // x is passed in the soln vector void compute_residual (const NumericVector<Number>& soln, NumericVector<Number>& residual, NonlinearImplicitSystem& sys) { EquationSystems &es = *_equation_system; // Get a constant reference to the mesh object. const MeshBase& mesh = es.get_mesh(); // The dimension that we are running const unsigned int dim = mesh.mesh_dimension(); libmesh_assert_equal_to (dim, 2); // Get a reference to the NonlinearImplicitSystem we are solving NonlinearImplicitSystem& system = es.get_system<NonlinearImplicitSystem>("Laplace-Young"); // A reference to the \p DofMap object for this system. The \p DofMap // object handles the index translation from node and element numbers // to degree of freedom numbers. We will talk more about the \p DofMap // in future examples. const DofMap& dof_map = system.get_dof_map(); // Get a constant reference to the Finite Element type // for the first (and only) variable in the system. FEType fe_type = dof_map.variable_type(0); // Build a Finite Element object of the specified type. Since the // \p FEBase::build() member dynamically creates memory we will // store the object as an \p AutoPtr<FEBase>. This can be thought // of as a pointer that will clean up after itself. AutoPtr<FEBase> fe (FEBase::build(dim, fe_type)); // A 5th order Gauss quadrature rule for numerical integration. QGauss qrule (dim, FIFTH); // Tell the finite element object to use our quadrature rule. fe->attach_quadrature_rule (&qrule); // Declare a special finite element object for // boundary integration. AutoPtr<FEBase> fe_face (FEBase::build(dim, fe_type)); // Boundary integration requires one quadraure rule, // with dimensionality one less than the dimensionality // of the element. QGauss qface(dim-1, FIFTH); // Tell the finte element object to use our // quadrature rule. fe_face->attach_quadrature_rule (&qface); // Here we define some references to cell-specific data that // will be used to assemble the linear system. // We begin with the element Jacobian * quadrature weight at each // integration point. const std::vector<Real>& JxW = fe->get_JxW(); // The element shape functions evaluated at the quadrature points. const std::vector<std::vector<Real> >& phi = fe->get_phi(); // The element shape function gradients evaluated at the quadrature // points. const std::vector<std::vector<RealGradient> >& dphi = fe->get_dphi(); // Define data structures to contain the resdual contributions DenseVector<Number> Re; // This vector will hold the degree of freedom indices for // the element. These define where in the global system // the element degrees of freedom get mapped. std::vector<unsigned int> dof_indices; // Now we will loop over all the active elements in the mesh which // are local to this processor. // We will compute the element residual. residual.zero(); MeshBase::const_element_iterator el = mesh.active_local_elements_begin(); const MeshBase::const_element_iterator end_el = mesh.active_local_elements_end(); for ( ; el != end_el; ++el) { // Store a pointer to the element we are currently // working on. This allows for nicer syntax later. const Elem* elem = *el; // Get the degree of freedom indices for the // current element. These define where in the global // matrix and right-hand-side this element will // contribute to. dof_map.dof_indices (elem, dof_indices); // Compute the element-specific data for the current // element. This involves computing the location of the // quadrature points (q_point) and the shape functions // (phi, dphi) for the current element. fe->reinit (elem); // We use the resize member here because // the number of degrees of freedom might have changed from // the last element. Note that this will be the case if the // element type is different (i.e. the last element was a // triangle, now we are on a quadrilateral). Re.resize (dof_indices.size()); // Now we will build the residual. This involves // the construction of the matrix K and multiplication of it // with the current solution x. We rearrange this into two loops: // In the first, we calculate only the contribution of // K_ij*x_j which is independent of the row i. In the second loops, // we multiply with the row-dependent part and add it to the element // residual. for (unsigned int qp=0; qp<qrule.n_points(); qp++) { Number u = 0; Gradient grad_u; for (unsigned int j=0; j<phi.size(); j++) { u += phi[j][qp]*soln(dof_indices[j]); grad_u += dphi[j][qp]*soln(dof_indices[j]); } const Number K = 1./std::sqrt(1. + grad_u*grad_u); for (unsigned int i=0; i<phi.size(); i++) Re(i) += JxW[qp]*( K*(dphi[i][qp]*grad_u) + kappa*phi[i][qp]*u ); } // At this point the interior element integration has // been completed. However, we have not yet addressed // boundary conditions. // The following loops over the sides of the element. // If the element has no neighbor on a side then that // side MUST live on a boundary of the domain. for (unsigned int side=0; side<elem->n_sides(); side++) if (elem->neighbor(side) == NULL) { // The value of the shape functions at the quadrature // points. const std::vector<std::vector<Real> >& phi_face = fe_face->get_phi(); // The Jacobian * Quadrature Weight at the quadrature // points on the face. const std::vector<Real>& JxW_face = fe_face->get_JxW(); // Compute the shape function values on the element face. fe_face->reinit(elem, side); // Loop over the face quadrature points for integration. for (unsigned int qp=0; qp<qface.n_points(); qp++) { // This is the right-hand-side contribution (f), // which has to be subtracted from the current residual for (unsigned int i=0; i<phi_face.size(); i++) Re(i) -= JxW_face[qp]*sigma*phi_face[i][qp]; } } dof_map.constrain_element_vector (Re, dof_indices); residual.add_vector (Re, dof_indices); } // That's it. }
void AssembleOptimization::assemble_A_and_F() { A_matrix->zero(); F_vector->zero(); const MeshBase & mesh = _sys.get_mesh(); const unsigned int dim = mesh.mesh_dimension(); const unsigned int u_var = _sys.variable_number ("u"); const DofMap & dof_map = _sys.get_dof_map(); FEType fe_type = dof_map.variable_type(u_var); UniquePtr<FEBase> fe (FEBase::build(dim, fe_type)); QGauss qrule (dim, fe_type.default_quadrature_order()); fe->attach_quadrature_rule (&qrule); const std::vector<Real> & JxW = fe->get_JxW(); const std::vector<std::vector<Real> > & phi = fe->get_phi(); const std::vector<std::vector<RealGradient> > & dphi = fe->get_dphi(); std::vector<dof_id_type> dof_indices; DenseMatrix<Number> Ke; DenseVector<Number> Fe; MeshBase::const_element_iterator el = mesh.active_local_elements_begin(); const MeshBase::const_element_iterator end_el = mesh.active_local_elements_end(); for ( ; el != end_el; ++el) { const Elem * elem = *el; dof_map.dof_indices (elem, dof_indices); const unsigned int n_dofs = dof_indices.size(); fe->reinit (elem); Ke.resize (n_dofs, n_dofs); Fe.resize (n_dofs); for (unsigned int qp=0; qp<qrule.n_points(); qp++) { for (unsigned int dof_i=0; dof_i<n_dofs; dof_i++) { for (unsigned int dof_j=0; dof_j<n_dofs; dof_j++) { Ke(dof_i, dof_j) += JxW[qp] * (dphi[dof_j][qp]* dphi[dof_i][qp]); } Fe(dof_i) += JxW[qp] * phi[dof_i][qp]; } } // This will zero off-diagonal entries of Ke corresponding to // Dirichlet dofs. dof_map.constrain_element_matrix_and_vector (Ke, Fe, dof_indices); // We want the diagonal of constrained dofs to be zero too for (unsigned int local_dof_index=0; local_dof_index<n_dofs; local_dof_index++) { dof_id_type global_dof_index = dof_indices[local_dof_index]; if (dof_map.is_constrained_dof(global_dof_index)) { Ke(local_dof_index, local_dof_index) = 0.; } } A_matrix->add_matrix (Ke, dof_indices); F_vector->add_vector (Fe, dof_indices); } A_matrix->close(); F_vector->close(); }
/** * Evaluate the residual of the nonlinear system. */ virtual void residual (const NumericVector<Number> & soln, NumericVector<Number> & residual, NonlinearImplicitSystem & /*sys*/) { const Real young_modulus = es.parameters.get<Real>("young_modulus"); const Real poisson_ratio = es.parameters.get<Real>("poisson_ratio"); const Real forcing_magnitude = es.parameters.get<Real>("forcing_magnitude"); const MeshBase & mesh = es.get_mesh(); const unsigned int dim = mesh.mesh_dimension(); NonlinearImplicitSystem & system = es.get_system<NonlinearImplicitSystem>("NonlinearElasticity"); const unsigned int u_var = system.variable_number ("u"); const DofMap & dof_map = system.get_dof_map(); FEType fe_type = dof_map.variable_type(u_var); std::unique_ptr<FEBase> fe (FEBase::build(dim, fe_type)); QGauss qrule (dim, fe_type.default_quadrature_order()); fe->attach_quadrature_rule (&qrule); std::unique_ptr<FEBase> fe_face (FEBase::build(dim, fe_type)); QGauss qface (dim-1, fe_type.default_quadrature_order()); fe_face->attach_quadrature_rule (&qface); const std::vector<Real> & JxW = fe->get_JxW(); const std::vector<std::vector<Real>> & phi = fe->get_phi(); const std::vector<std::vector<RealGradient>> & dphi = fe->get_dphi(); DenseVector<Number> Re; DenseSubVector<Number> Re_var[3] = {DenseSubVector<Number>(Re), DenseSubVector<Number>(Re), DenseSubVector<Number>(Re)}; std::vector<dof_id_type> dof_indices; std::vector<std::vector<dof_id_type>> dof_indices_var(3); residual.zero(); for (const auto & elem : mesh.active_local_element_ptr_range()) { dof_map.dof_indices (elem, dof_indices); for (unsigned int var=0; var<3; var++) dof_map.dof_indices (elem, dof_indices_var[var], var); const unsigned int n_dofs = dof_indices.size(); const unsigned int n_var_dofs = dof_indices_var[0].size(); fe->reinit (elem); Re.resize (n_dofs); for (unsigned int var=0; var<3; var++) Re_var[var].reposition (var*n_var_dofs, n_var_dofs); for (unsigned int qp=0; qp<qrule.n_points(); qp++) { DenseVector<Number> u_vec(3); DenseMatrix<Number> grad_u(3, 3); for (unsigned int var_i=0; var_i<3; var_i++) { for (unsigned int j=0; j<n_var_dofs; j++) u_vec(var_i) += phi[j][qp]*soln(dof_indices_var[var_i][j]); // Row is variable u, v, or w column is x, y, or z for (unsigned int var_j=0; var_j<3; var_j++) for (unsigned int j=0; j<n_var_dofs; j++) grad_u(var_i,var_j) += dphi[j][qp](var_j)*soln(dof_indices_var[var_i][j]); } DenseMatrix<Number> strain_tensor(3, 3); for (unsigned int i=0; i<3; i++) for (unsigned int j=0; j<3; j++) { strain_tensor(i,j) += 0.5 * (grad_u(i,j) + grad_u(j,i)); for (unsigned int k=0; k<3; k++) strain_tensor(i,j) += 0.5 * grad_u(k,i)*grad_u(k,j); } // Define the deformation gradient DenseMatrix<Number> F(3, 3); F = grad_u; for (unsigned int var=0; var<3; var++) F(var, var) += 1.; DenseMatrix<Number> stress_tensor(3, 3); for (unsigned int i=0; i<3; i++) for (unsigned int j=0; j<3; j++) for (unsigned int k=0; k<3; k++) for (unsigned int l=0; l<3; l++) stress_tensor(i,j) += elasticity_tensor(young_modulus, poisson_ratio, i, j, k, l) * strain_tensor(k,l); DenseVector<Number> f_vec(3); f_vec(0) = 0.; f_vec(1) = 0.; f_vec(2) = -forcing_magnitude; for (unsigned int dof_i=0; dof_i<n_var_dofs; dof_i++) for (unsigned int i=0; i<3; i++) { for (unsigned int j=0; j<3; j++) { Number FxStress_ij = 0.; for (unsigned int m=0; m<3; m++) FxStress_ij += F(i,m) * stress_tensor(m,j); Re_var[i](dof_i) += JxW[qp] * (-FxStress_ij * dphi[dof_i][qp](j)); } Re_var[i](dof_i) += JxW[qp] * (f_vec(i) * phi[dof_i][qp]); } } dof_map.constrain_element_vector (Re, dof_indices); residual.add_vector (Re, dof_indices); } }
//------------------------------------------------------------------------------------------------------------ void AssembleMatrixRes_VC(MultiLevelProblem &ml_prob) { TransientNonlinearImplicitSystem* mlPdeSys = & ml_prob.get_system<TransientNonlinearImplicitSystem>("Timedep"); const unsigned level = mlPdeSys->GetLevelToAssemble(); MultiLevelSolution *ml_sol = ml_prob._ml_sol; Solution* sol = ml_sol->GetSolutionLevel(level); LinearEquationSolver* pdeSys = mlPdeSys->_LinSolver[level]; const char* pdename = mlPdeSys->name().c_str(); Mesh* msh = ml_prob._ml_msh->GetLevel(level); elem* myel = msh->el; SparseMatrix* JAC = pdeSys->_KK; NumericVector* RES = pdeSys->_RES; // data const unsigned dim = msh->GetDimension(); const unsigned max_size = static_cast< unsigned >(ceil(pow(3, dim))); // conservative: based on line3, quad9, hex27 unsigned nel = msh->GetNumberOfElements(); unsigned igrid = msh->GetLevel(); unsigned iproc = msh->processor_id(); // time dep data double dt = mlPdeSys->GetIntervalTime(); // double theta = 0.5; //************** geometry (at dofs and quadrature points) ************************************* vector < vector < double > > coords_at_dofs(dim); unsigned coords_fe_type = BIQUADR_FE; // get the finite element type for "x", it is always 2 (LAGRANGE BIQUADRATIC) for (unsigned i = 0; i < coords_at_dofs.size(); i++) coords_at_dofs[i].reserve(max_size); vector < double > coord_at_qp(dim); //************* shape functions (at dofs and quadrature points) ************************************** const int solType_max = BIQUADR_FE; //biquadratic double weight_qp; // gauss point weight vector < vector < double > > phi_fe_qp(NFE_FAMS); vector < vector < double > > phi_x_fe_qp(NFE_FAMS); vector < vector < double > > phi_xx_fe_qp(NFE_FAMS); for(int fe=0; fe < NFE_FAMS; fe++) { phi_fe_qp[fe].reserve(max_size); phi_x_fe_qp[fe].reserve(max_size*dim); phi_xx_fe_qp[fe].reserve(max_size*(3*(dim-1))); } //*************************************************** //********* WHOLE SET OF VARIABLES ****************** //*************************************************** const unsigned int n_unknowns = mlPdeSys->GetSolPdeIndex().size(); vector < std::string > Solname(n_unknowns); Solname[0] = "u"; vector < unsigned > SolPdeIndex(n_unknowns); vector < unsigned > SolIndex(n_unknowns); vector < unsigned int > SolFEType(n_unknowns); //FEtype of each MultilevelSolution vector < unsigned int > Sol_n_el_dofs(n_unknowns); //number of element dofs std::fill(Sol_n_el_dofs.begin(), Sol_n_el_dofs.end(), 0); for(unsigned ivar=0; ivar < n_unknowns; ivar++) { SolPdeIndex[ivar] = mlPdeSys->GetSolPdeIndex( Solname[ivar].c_str() ); SolIndex[ivar] = ml_sol->GetIndex ( Solname[ivar].c_str() ); SolFEType[ivar] = ml_sol->GetSolutionType ( SolIndex[ivar]); } //------------ quantities (at quadrature points) --------------------- vector<double> sol_qp(n_unknowns); vector<double> sol_old_qp(n_unknowns); vector< vector<double> > sol_grad_qp(n_unknowns); vector< vector<double> > sol_old_grad_qp(n_unknowns); std::fill(sol_qp.begin(), sol_qp.end(), 0.); std::fill(sol_old_qp.begin(), sol_old_qp.end(), 0.); for (unsigned k = 0; k < n_unknowns; k++) { sol_grad_qp[k].resize(dim); std::fill(sol_grad_qp[k].begin(), sol_grad_qp[k].end(), 0.); sol_old_grad_qp[k].resize(dim); std::fill(sol_old_grad_qp[k].begin(), sol_old_grad_qp[k].end(), 0.); } //----------- quantities (at dof objects) ------------------------------ vector < vector < double > > sol_eldofs(n_unknowns); vector < vector < double > > sol_old_eldofs(n_unknowns); for(int k=0; k<n_unknowns; k++) { sol_eldofs[k].reserve(max_size); sol_old_eldofs[k].reserve(max_size); } //******** linear system ******************************************* vector < vector < int > > L2G_dofmap(n_unknowns); for(int i = 0; i < n_unknowns; i++) { L2G_dofmap[i].reserve(max_size); } vector< int > L2G_dofmap_AllVars; L2G_dofmap_AllVars.reserve( n_unknowns*max_size ); vector< vector< double > > Res_el(n_unknowns); vector< vector< vector< double > > > Jac_el(n_unknowns); for(int i = 0; i < n_unknowns; i++) Res_el[i].reserve(max_size); for(int i = 0; i < n_unknowns; i++) { Jac_el[i].resize(n_unknowns); for(int j = 0; j < n_unknowns; j++) { Jac_el[i][j].reserve(max_size*max_size); } } // Set to zero all the entries of the matrix RES->zero(); JAC->zero(); const double deltat_term = 1.; const double lapl_term = 1.; const double delta_g_term = 1.; // *** element loop *** for (int iel = msh->_elementOffset[iproc]; iel < msh->_elementOffset[iproc+1]; iel++) { short unsigned ielGeom = msh->GetElementType(iel); // element geometry type //******************** GEOMETRY ********************* unsigned nDofx = msh->GetElementDofNumber(iel, coords_fe_type); // number of coordinate element dofs for (int i = 0; i < dim; i++) coords_at_dofs[i].resize(nDofx); // local storage of coordinates for (unsigned i = 0; i < nDofx; i++) { unsigned xDof = msh->GetSolutionDof(i, iel, coords_fe_type); // global to global mapping between coordinates node and coordinate dof for (unsigned jdim = 0; jdim < dim; jdim++) { coords_at_dofs[jdim][i] = (*msh->_topology->_Sol[jdim])(xDof); // global extraction and local storage for the element coordinates } } //*************************************************** //all vars################################################################### for (unsigned k = 0; k < n_unknowns; k++) { unsigned ndofs_unk = msh->GetElementDofNumber(iel, SolFEType[k]); Sol_n_el_dofs[k] = ndofs_unk; sol_eldofs[k].resize(ndofs_unk); sol_old_eldofs[k].resize(ndofs_unk); L2G_dofmap[k].resize(ndofs_unk); for (unsigned i = 0; i < ndofs_unk; i++) { unsigned solDof = msh->GetSolutionDof(i, iel, SolFEType[k]); // global to global mapping between solution node and solution dof // via local to global solution node sol_eldofs[k][i] = (*sol->_Sol[SolIndex[k]])(solDof); // global extraction and local storage for the solution sol_old_eldofs[k][i] = (*sol->_SolOld[SolIndex[k]])(solDof); // This is OLD in TIME, not in nonlinear loop L2G_dofmap[k][i] = pdeSys->GetSystemDof(SolIndex[k], SolPdeIndex[k], i, iel); // global to global mapping between solution node and pdeSys dof } } unsigned nDof_AllVars = 0; for (unsigned k = 0; k < n_unknowns; k++) { nDof_AllVars += Sol_n_el_dofs[k]; } // TODO COMPUTE MAXIMUM maximum number of element dofs for one scalar variable int nDof_max = 0; for (unsigned k = 0; k < n_unknowns; k++) { if(Sol_n_el_dofs[k] > nDof_max) nDof_max = Sol_n_el_dofs[k]; } for(int k = 0; k < n_unknowns; k++) { L2G_dofmap[k].resize(Sol_n_el_dofs[k]); Res_el[SolPdeIndex[k]].resize(Sol_n_el_dofs[k]); memset(& Res_el[SolPdeIndex[k]][0], 0., Sol_n_el_dofs[k] * sizeof(double) ); Jac_el[SolPdeIndex[k]][SolPdeIndex[k]].resize(Sol_n_el_dofs[k] * Sol_n_el_dofs[k]); memset(& Jac_el[SolPdeIndex[k]][SolPdeIndex[k]][0], 0., Sol_n_el_dofs[k] * Sol_n_el_dofs[k] * sizeof(double)); } //all vars################################################################### // *** quadrature loop *** for(unsigned ig = 0; ig < ml_prob.GetQuadratureRule(ielGeom).GetGaussPointsNumber(); ig++) { // *** get gauss point weight, test function and test function partial derivatives *** for(int fe=0; fe < NFE_FAMS; fe++) { msh->_finiteElement[ielGeom][fe]->Jacobian(coords_at_dofs,ig,weight_qp,phi_fe_qp[fe],phi_x_fe_qp[fe],phi_xx_fe_qp[fe]); } //HAVE TO RECALL IT TO HAVE BIQUADRATIC JACOBIAN msh->_finiteElement[ielGeom][coords_fe_type]->Jacobian(coords_at_dofs,ig,weight_qp,phi_fe_qp[coords_fe_type],phi_x_fe_qp[coords_fe_type],phi_xx_fe_qp[coords_fe_type]); //========= fill gauss value quantities ================== std::fill(sol_qp.begin(), sol_qp.end(), 0.); std::fill(sol_old_qp.begin(), sol_old_qp.end(), 0.); for (unsigned k = 0; k < n_unknowns; k++) { std::fill(sol_grad_qp[k].begin(), sol_grad_qp[k].end(), 0.); std::fill(sol_old_grad_qp[k].begin(), sol_old_grad_qp[k].end(), 0.); } for (unsigned k = 0; k < n_unknowns; k++) { for (unsigned i = 0; i < Sol_n_el_dofs[k]; i++) { sol_qp[k] += sol_eldofs[k][i] * phi_fe_qp[SolFEType[k]][i]; sol_old_qp[k] += sol_old_eldofs[k][i] * phi_fe_qp[SolFEType[k]][i]; for (unsigned d = 0; d < dim; d++) { sol_grad_qp[k][d] += sol_eldofs[k][i] * phi_x_fe_qp[SolFEType[k]][i * dim + d]; sol_old_grad_qp[k][d] += sol_old_eldofs[k][i] * phi_x_fe_qp[SolFEType[k]][i * dim + d]; } } } //========= fill gauss value quantities ================== // *** phi_i loop *** for(unsigned i = 0; i < nDof_max; i++) { //BEGIN RESIDUALS A block =========================== double Lap_rhs_i = 0.; double Lap_old_rhs_i = 0.; for(unsigned d = 0; d < dim; d++) { Lap_rhs_i += phi_x_fe_qp[SolFEType[0]][i * dim + d] * sol_grad_qp[0][d]; Lap_old_rhs_i += phi_x_fe_qp[SolFEType[0]][i * dim + d] * sol_old_grad_qp[0][d]; } Res_el[SolPdeIndex[0]][i] += - weight_qp * ( delta_g_term * Singularity::function(sol_qp[0]) * Singularity::g_vc(sol_qp[0]) * phi_fe_qp[ SolFEType[0] ][i] - delta_g_term * Singularity::function(sol_qp[0]) * Singularity::g_vc(sol_old_qp[0]) * phi_fe_qp[ SolFEType[0] ][i] + deltat_term * Singularity::function(sol_qp[0]) * dt * phi_fe_qp[ SolFEType[0] ][i] + lapl_term * dt * Lap_rhs_i ); //END RESIDUALS A block =========================== // *** phi_j loop *** for(unsigned j = 0; j<nDof_max; j++) { double Lap_mat_i_j = 0.; for(unsigned d = 0; d < dim; d++) Lap_mat_i_j += phi_x_fe_qp[SolFEType[0]][i * dim + d] * phi_x_fe_qp[SolFEType[0]][j * dim + d]; Jac_el[SolPdeIndex[0]][SolPdeIndex[0]][i * Sol_n_el_dofs[0] + j] += weight_qp * ( + delta_g_term * phi_fe_qp[ SolFEType[0] ][i] * Singularity::derivative( phi_fe_qp[ SolFEType[0] ][j] ) * phi_fe_qp[ SolFEType[0] ][j] * Singularity::g_vc( phi_fe_qp[ SolFEType[0] ][j] ) + delta_g_term * phi_fe_qp[ SolFEType[0] ][i] * Singularity::function ( phi_fe_qp[ SolFEType[0] ][j] ) * Singularity::g_vc_derivative( phi_fe_qp[ SolFEType[0] ][j] ) * phi_fe_qp[ SolFEType[0] ][j] - delta_g_term * phi_fe_qp[ SolFEType[0] ][i] * Singularity::derivative( phi_fe_qp[ SolFEType[0] ][j] ) * phi_fe_qp[ SolFEType[0] ][j] * Singularity::g_vc( sol_old_qp[0] ) + deltat_term * phi_fe_qp[ SolFEType[0] ][i] * Singularity::derivative( phi_fe_qp[ SolFEType[0] ][j] ) * phi_fe_qp[ SolFEType[0] ][j] * dt + lapl_term * dt * Lap_mat_i_j ); } //end phij loop } //end phii loop } // end gauss point loop //-------------------------------------------------------------------------------------------------------- //Sum the local matrices/vectors into the Global Matrix/Vector for(unsigned ivar=0; ivar < n_unknowns; ivar++) { RES->add_vector_blocked(Res_el[SolPdeIndex[ivar]],L2G_dofmap[ivar]); JAC->add_matrix_blocked(Jac_el[SolPdeIndex[ivar]][SolPdeIndex[ivar]],L2G_dofmap[ivar],L2G_dofmap[ivar]); } //-------------------------------------------------------------------------------------------------------- } //end list of elements loop for each subdomain JAC->close(); RES->close(); // ***************** END ASSEMBLY ******************* }