inline double FunctionIntegral (const uint vb, MultiLevelProblem & ml_prob, double (*pt2func)(double, const std::vector<double> ) ) { const uint mesh_vb = vb; const uint Level = ml_prob.GetMeshTwo()._NoLevels - 1; const uint myproc = ml_prob.GetMeshTwo()._iproc; double time = 0.; Mesh *mymsh = ml_prob._ml_msh->GetLevel(Level); double integral = 0.; //parallel sum const uint nel_e = ml_prob.GetMeshTwo()._off_el[mesh_vb][ml_prob.GetMeshTwo()._NoLevels*myproc+Level+1]; const uint nel_b = ml_prob.GetMeshTwo()._off_el[mesh_vb][ml_prob.GetMeshTwo()._NoLevels*myproc+Level]; for (uint iel=0; iel < (nel_e - nel_b); iel++) { CurrentElem currelem(iel,myproc,Level,vb,NULL,ml_prob.GetMeshTwo(),ml_prob.GetElemType(),mymsh); //element without equation CurrentGaussPointBase & currgp = CurrentGaussPointBase::build(currelem,ml_prob.GetQrule(currelem.GetDim())); const uint el_ngauss = ml_prob.GetQrule(currelem.GetDim()).GetGaussPointsNumber(); //========= DOMAIN MAPPING CurrentQuantity xyz(currgp); xyz._dim = ml_prob.GetMeshTwo().get_dim(); xyz._FEord = MESH_MAPPING_FE; xyz._ndof = currelem.GetElemType(xyz._FEord)->GetNDofs(); xyz.Allocate(); currelem.SetDofobjConnCoords(); currelem.ConvertElemCoordsToMappingOrd(xyz); for (uint qp = 0; qp < el_ngauss; qp++) { for (uint fe = 0; fe < QL; fe++) { currgp.SetPhiElDofsFEVB_g (fe,qp); currgp.SetDPhiDxezetaElDofsFEVB_g (fe,qp); } double Jac_g=0.; if (vb==0) Jac_g = currgp.JacVectVV_g(xyz); //not xyz_refbox! else if (vb==1) Jac_g = currgp.JacVectBB_g(xyz); //not xyz_refbox! const double wgt_g = ml_prob.GetQrule(currelem.GetDim()).GetGaussWeight(qp); xyz.val_g(); double myval_g = pt2func(time,xyz._val_g); integral += wgt_g*Jac_g*myval_g; }//gauss loop }//element loop std::cout << std::endl << " ^^^^^^^^^^^^^^^^^L'integrale sul processore "<< myproc << " vale: " << integral << std::endl; // double weights_sum = 0.; // for (uint qp = 0; qp < el_ngauss; qp++) weights_sum += ml_prob.GetQrule(currelem.GetDim()).GetGaussWeight(qp); // std::cout << std::endl << " ^^^^^^^^^^^^^^^^^ La somma dei pesi vale: " << weights_sum << std::endl; double J=0.; #ifdef HAVE_MPI // MPI_Reduce( &integral, &J, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD ); //This one gives J only to processor 0 ! MPI_Allreduce( &integral, &J, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD ); //THIS IS THE RIGHT ONE!! #else J = integral; #endif std::cout << std::endl << " ^^^^^^^^^^^^^^^^^L'integrale totale vale: " << J << std::endl; return J; }
void GenMatRhsMHD(MultiLevelProblem &ml_prob) { SystemTwo & my_system = ml_prob.get_system<SystemTwo>("Eqn_MHD"); const unsigned Level = my_system.GetLevelToAssemble(); //========= reference values ========= const double IRem = 1./ml_prob.GetInputParser().get("Rem"); //============================ //======== GEOMETRICAL ELEMENT ======= const uint space_dim = ml_prob._ml_msh->GetDimension(); //==== Operators @ gauss ======== std::vector<double> Vel_vec_val_g(space_dim); std::vector<double> Vel_vec_val_g3D(3); std::vector<double> Bext_vec_val_g(space_dim); std::vector<double> Bext_vec_val_g3D(3); double vXBe_g3D[3]; double vXBeXdphii_g3D[3]; double curlBeXdphii_g3D[3]; double LapBe_g[DIMENSION]; //============================ my_system._LinSolver[Level]->_KK->zero(); my_system._LinSolver[Level]->_RESC->zero(); // ========================================== Mesh *mymsh = ml_prob._ml_msh->GetLevel(Level); elem *myel = mymsh->el; const unsigned myproc = mymsh->processor_id(); // ========================================== // ========================================== {//BEGIN VOLUME const uint mesh_vb = VV; const uint nel_e = ml_prob.GetMeshTwo()._off_el[mesh_vb][ml_prob.GetMeshTwo()._NoLevels*myproc+Level+1]; const uint nel_b = ml_prob.GetMeshTwo()._off_el[mesh_vb][ml_prob.GetMeshTwo()._NoLevels*myproc+Level]; for (uint iel=0; iel < (nel_e - nel_b); iel++) { CurrentElem<double> currelem(iel,myproc,Level,VV,&my_system,ml_prob.GetMeshTwo(),ml_prob.GetElemType(),mymsh); CurrentGaussPointBase & currgp = CurrentGaussPointBase::build(currelem,ml_prob.GetQuadratureRule(currelem.GetDim())); //=========INTERNAL QUANTITIES (unknowns of the equation) ================== CurrentQuantity BhomOldX(currgp); BhomOldX._qtyptr = ml_prob.GetQtyMap().GetQuantity("Qty_MagnFieldHom0"); BhomOldX.VectWithQtyFillBasic(); BhomOldX.Allocate(); CurrentQuantity BhomOldY(currgp); BhomOldY._qtyptr = ml_prob.GetQtyMap().GetQuantity("Qty_MagnFieldHom1"); BhomOldY.VectWithQtyFillBasic(); BhomOldY.Allocate(); CurrentQuantity BhomOldZ(currgp); BhomOldZ._qtyptr = ml_prob.GetQtyMap().GetQuantity("Qty_MagnFieldHom2"); BhomOldZ.VectWithQtyFillBasic(); BhomOldZ.Allocate(); std::vector<CurrentQuantity*> BhomOld_vec; BhomOld_vec.push_back(&BhomOldX); BhomOld_vec.push_back(&BhomOldY); BhomOld_vec.push_back(&BhomOldZ); CurrentQuantity LagMultOld(currgp); LagMultOld._qtyptr = ml_prob.GetQtyMap().GetQuantity("Qty_MagnFieldHomLagMult"); LagMultOld.VectWithQtyFillBasic(); LagMultOld.Allocate(); //========= END INTERNAL QUANTITIES (unknowns of the equation) ================= //========= tEST AND SHAPE FOR QTYZERO AND QTYONE ================= //QTYZERO SHAPE: shape of the first Unknown CurrentQuantity Phij(currgp); //TODO this is another Vect that doesnt have an associated quantity still Phij._dim = 1; //scalar! Phij._FEord = BhomOldX._FEord; Phij._ndof = currelem.GetElemType(Phij._FEord)->GetNDofs(); Phij.Allocate(); //QTYZERO tEST: test of the first Unknown CurrentQuantity Phii(currgp); Phii._dim = 1; Phii._FEord = BhomOldX._FEord; Phii._ndof = currelem.GetElemType(Phii._FEord)->GetNDofs(); Phii.Allocate(); //QTYONE SHAPE: Shape of the second Unknown CurrentQuantity Psij(currgp); Psij._dim = 1; Psij._FEord = LagMultOld._FEord; Psij._ndof = currelem.GetElemType(Psij._FEord)->GetNDofs(); Psij.Allocate(); //QTYONE tEST: test of the second Unknown CurrentQuantity Psii(currgp); Psii._dim = 1; Psii._FEord = LagMultOld._FEord; Psii._ndof = currelem.GetElemType(Psii._FEord)->GetNDofs(); Psii.Allocate(); //========= END tEST AND SHAPE FOR QTYZERO AND QTYONE ================= //=========EXTERNAL QUANTITIES (couplings) ===== //========= //DOMAIN MAPPING CurrentQuantity xyz(currgp); xyz._dim = DIMENSION; xyz._FEord = MESH_MAPPING_FE; xyz._ndof = currelem.GetElemType(xyz._FEord)->GetNDofs(); xyz.Allocate(); CurrentQuantity BextX(currgp); BextX._qtyptr = ml_prob.GetQtyMap().GetQuantity("Qty_MagnFieldExt0"); BextX.VectWithQtyFillBasic(); BextX.Allocate(); CurrentQuantity BextY(currgp); BextY._qtyptr = ml_prob.GetQtyMap().GetQuantity("Qty_MagnFieldExt1"); BextY.VectWithQtyFillBasic(); BextY.Allocate(); CurrentQuantity BextZ(currgp); BextZ._qtyptr = ml_prob.GetQtyMap().GetQuantity("Qty_MagnFieldExt2"); BextZ.VectWithQtyFillBasic(); BextZ.Allocate(); std::vector<CurrentQuantity*> Bext_vec; Bext_vec.push_back(&BextX); Bext_vec.push_back(&BextY); Bext_vec.push_back(&BextZ); CurrentQuantity Bext_vecQuant(currgp); //without quantity, nor equation Bext_vecQuant._dim = Bext_vec.size(); Bext_vecQuant._FEord = Bext_vec[0]->_FEord; Bext_vecQuant._ndof = Bext_vec[0]->_ndof; Bext_vecQuant.Allocate(); CurrentQuantity VelX(currgp); VelX._qtyptr = ml_prob.GetQtyMap().GetQuantity("Qty_Velocity0"); VelX.VectWithQtyFillBasic(); VelX.Allocate(); CurrentQuantity VelY(currgp); VelY._qtyptr = ml_prob.GetQtyMap().GetQuantity("Qty_Velocity1"); VelY.VectWithQtyFillBasic(); VelY.Allocate(); CurrentQuantity VelZ(currgp); VelZ._qtyptr = ml_prob.GetQtyMap().GetQuantity("Qty_Velocity2"); VelZ.VectWithQtyFillBasic(); VelZ.Allocate(); std::vector<CurrentQuantity*> Vel_vec; Vel_vec.push_back(&VelX); Vel_vec.push_back(&VelY); Vel_vec.push_back(&VelZ); //=========END EXTERNAL QUANTITIES (couplings) ===== //====================== //====================== currelem.Mat().zero(); currelem.Rhs().zero(); currelem.SetDofobjConnCoords(); currelem.SetElDofsBc(); currelem.ConvertElemCoordsToMappingOrd(xyz); for (uint idim=0; idim < space_dim; idim++) { BhomOld_vec[idim]->GetElemDofs(); Vel_vec[idim]->GetElemDofs(); Bext_vec[idim]->GetElemDofs(); } Bext_vecQuant.GetElemDofs(Bext_vec); const uint el_ngauss = ml_prob.GetQuadratureRule(currelem.GetDim()).GetGaussPointsNumber(); for (uint qp = 0; qp < el_ngauss; qp++) { //======= here starts the "COMMON SHAPE PART"================== for (uint fe = 0; fe < QL; fe++) { currgp.SetPhiElDofsFEVB_g (fe,qp); currgp.SetDPhiDxezetaElDofsFEVB_g (fe,qp); } const double det = currgp.JacVectVV_g(xyz); //InvJac: is unique! const double dtxJxW_g = det*ml_prob.GetQuadratureRule(currelem.GetDim()).GetGaussWeight(qp); const double detb = det/el_ngauss; for (uint fe = 0; fe < QL; fe++) { currgp.SetDPhiDxyzElDofsFEVB_g (fe,qp); currgp.ExtendDphiDxyzElDofsFEVB_g (fe); } //======= end of the "COMMON SHAPE PART"================== for (uint idim=0; idim < space_dim; idim++) { BhomOld_vec[idim]->val_g(); Vel_vec[idim]->val_g(); //---- for Advection MAT & RHS Vel_vec_val_g[idim] = Vel_vec[idim]->_val_g[0]; Bext_vec[idim]->val_g(); //----- for Advection RHS Bext_vec_val_g[idim] = Bext_vec[idim]->_val_g[0]; Bext_vec[idim]->grad_g(); //----- for Laplacian RHS } Bext_vecQuant.curl_g(); //----- for Curl Curl RHS //THE EXTENSION of the DOFS to 3D is done INSIDE!! Math::extend(&Vel_vec_val_g[0],&Vel_vec_val_g3D[0],space_dim); //----- for Advection RHS Math::extend(&Bext_vec_val_g[0],&Bext_vec_val_g3D[0],space_dim); //----- for Advection RHS Math::cross(&Vel_vec_val_g3D[0],&Bext_vec_val_g3D[0],vXBe_g3D); //----- for Advection RHS //================================ //========= FILLING ELEMENT MAT/RHS //================================= for (uint i=0; i < BhomOldX._ndof; i++) { //============ preparation for (i) (Phii) ============ Phii._val_g[0] = currgp._phi_ndsQLVB_g[Phii._FEord][i]; /*const double phii_g*/ for (uint idim=0; idim<space_dim; idim++) Phii._grad_g[0][idim] = currgp._dphidxyz_ndsQLVB_g[Phii._FEord][i+idim*Phii._ndof]; /*dphiidx_g*/ //=== from this point on, the dependency on /*(i)*/, the ROW INDEX, of the quantities is given by Phii //=== /*(i)*/ is ONLY used for the POSITIONS, later //--------- LAPLACIAN: Operator, RHS: grad Be . grad phi --------------------- for (uint idim=0; idim<space_dim/*Bext._dim*/; idim++) LapBe_g[idim]=0.; for (uint idim=0; idim<space_dim/*Bext._dim*/; idim++) { for (uint jdim=0; jdim<space_dim; jdim++) { LapBe_g[idim] += Bext_vec[idim]->_grad_g[0][jdim]*Phii._grad_g[0][jdim]; } } Math::extend(&Phii._grad_g[0][0],&Phii._grad_g3D[0][0],space_dim); //--------- CURL CURL: Operator, RHS: curl Be . curl phi ------------------- Math::cross(&Bext_vecQuant._curl_g3D[0],&Phii._grad_g3D[0][0],curlBeXdphii_g3D); //--------- ADVECTION: Operator, RHS: v x Be . curl phi ------------------- Math::cross( vXBe_g3D,&Phii._grad_g3D[0][0], vXBeXdphii_g3D); // _utils.cross(vXBe_g3D,dphiidx_g3D,vXBeXdphii_g3D); //============end preparation for (i) ============ for (uint idim=0; idim<space_dim/*bhomOld._dim*/; idim++) { const uint irowq = i + idim*BhomOldX._ndof; currelem.Rhs()(irowq) += currelem.GetBCDofFlag()[irowq]*dtxJxW_g*( - LAP_MHD*IRem*LapBe_g[idim] - (1-LAP_MHD)*IRem*curlBeXdphii_g3D[idim] //phii of bhomOld /*CurlCurl(RHS,vb,Phij,Phii,idim,idimp1);*/ + ADV_MHD* vXBeXdphii_g3D[idim] //phii of bhomOld ) + (1-currelem.GetBCDofFlag()[irowq])*detb*BhomOld_vec[idim]->_val_dofs[i]; //Dirichlet bc } for (uint idim=0; idim<space_dim/*bhomOld._dim*/; idim++) { // filling diagonal block for Dirichlet bc const uint irowq = i + idim*BhomOldX._ndof; currelem.Mat()(irowq,irowq) += (1-currelem.GetBCDofFlag()[irowq])*detb; } // end filling diagonal for Dirichlet bc for (uint j=0; j<BhomOldX._ndof; j++) { // A element matrix //============ preparation for (j) (Phij) ============ Phij._val_g[0] = currgp._phi_ndsQLVB_g[Phij._FEord][j]; for (uint idim=0; idim<space_dim; idim++) Phij._grad_g[0][idim] = currgp._dphidxyz_ndsQLVB_g[Phij._FEord][j+idim*Phij._ndof]; //real shape /*dphijdx_g[idim]*/ //=== from this point on, the dependency on /*(j)*/, the COLUMN INDEX, of the quantities is given by Phij //=== /*(j)*/ is ONLY used for the POSITIONS, later //--------- LAPLACIAN: Operator, MAT: grad b . grad phi --------------------- double Lap_g = Math::dot(&Phij._grad_g[0][0],&Phii._grad_g[0][0],space_dim); /*(i,j)*/ //part independent of idim //--------- ADVECTION: Operator, MAT: v x b . curl phi ------------------- double Advphii_g = Math::dot( &Vel_vec_val_g[0],&Phii._grad_g[0][0],space_dim); /*(i)*/ //part independent of idim //TODO what about putting it OUTSIDE? for (uint idim=0; idim<space_dim/*bhomOld._dim*/; idim++) { //filled in as 1-2-3 // 5-6-4 // 9-7-8 int irowq=i+idim*BhomOldX._ndof; //idim gives the row index //test of bhomOld // diagonal blocks [1-5-9] idim = row index = column index //shape of bhomOld currelem.Mat()(irowq,j+idim*BhomOldX._ndof) += currelem.GetBCDofFlag()[irowq]*dtxJxW_g*( + LAP_MHD*IRem*(Lap_g) + (1-LAP_MHD)*IRem*( Lap_g - Phij._grad_g[0][idim]*Phii._grad_g[0][idim] ) - ADV_MHD * Phij._val_g[0]* (Advphii_g - Vel_vec[idim]->_val_g[0] *Phii._grad_g[0][idim] ) //TODO Phij here does not depend on idim, but it depends on j ); // block +1 [2-6-7] int idimp1=(idim+1)%space_dim; //idim: component of the SHAPE //idimp1: component of the tEST currelem.Mat()(irowq,j+idimp1*BhomOldX._ndof) += currelem.GetBCDofFlag()[irowq]*dtxJxW_g*( + (1-LAP_MHD)*IRem*( - Phij._grad_g[0][idim]*Phii._grad_g[0][idimp1] ) /*(i,j)*/ /*CurlCurl(MAT,vb,Phij,Phii,idim,idimp1);*/ - ADV_MHD * Phij._val_g[0]* ( - Vel_vec[idim]->_val_g[0] * Phii._grad_g[0][idimp1] ) /*(i,j)*/ /*AdvCurl(MAT,Vel,Phij,Phii,idim,idimp1)*/ ); #if (DIMENSION==3) // block +2 [3-4-8] int idimp2=(idim+2)%space_dim;//idimp2 column index currelem.Mat()(irowq,j+idimp2*BhomOldX._ndof) += currelem.GetBCDofFlag()[irowq]*dtxJxW_g*( + (1-LAP_MHD)*IRem*( - Phij._grad_g[0][idim]*Phii._grad_g[0][idimp2] ) /*(i,j)*/ - ADV_MHD * Phij._val_g[0]* ( - Vel_vec[idim]->_val_g[0] *Phii._grad_g[0][idimp2] ) /*(i,j)*/ ); #endif } } // end A element matrix for (uint j = 0; j < LagMultOld._ndof; j++) {// B^T element matrix ( p*div(v) ) Psij._val_g[0] = currgp._phi_ndsQLVB_g[Psij._FEord][j]; /*const double psij_g */ const int jclml= j+/*bhomOld._dim*/space_dim*BhomOldX._ndof; for (uint idim=0; idim<space_dim; idim++) { //bhomOld._dim==spacedimension uint irowq=i+idim*BhomOldX._ndof; currelem.Mat()(irowq,jclml) += currelem.GetBCDofFlag()[irowq]*dtxJxW_g*( - Psij._val_g[0]*Phii._grad_g[0][idim] ); /*(i,j)*/ /*PDiv(MAT,Psij,Phii,idim)*/ } } // end B^T element matrix //============ begin linear rows if (i < LagMultOld._ndof) { Psii._val_g[0] = currgp._phi_ndsQLVB_g[Psii._FEord][i]; /*double psii_g*/ const uint irowl=i+space_dim*BhomOldX._ndof; currelem.Rhs()(irowl)=0.; for (uint j=0; j<BhomOldX._ndof; j++) { // B element matrix q*div(u) for (uint idim=0; idim<space_dim; idim++) Phij._grad_g[0][idim] = currgp._dphidxyz_ndsQLVB_g[Phij._FEord][j+idim*Phij._ndof]; for (uint idim=0; idim<space_dim; idim++) currelem.Mat()(irowl,j+idim*BhomOldX._ndof) += - dtxJxW_g*Psii._val_g[0]*Phij._grad_g[0][idim]; /*(i,j)*/ /*PDiv(MAT,Psii,Phij,idim)*/ } } //============ end linear rows } //end filling element mat/rhs (i loop) } // end element gaussian integration loop /// Add element matrix and rhs to the global ones. my_system._LinSolver[Level]->_KK->add_matrix(currelem.Mat(),currelem.GetDofIndices()); my_system._LinSolver[Level]->_RESC->add_vector(currelem.Rhs(),currelem.GetDofIndices()); } // end of element loop }//END VOLUME my_system._LinSolver[Level]->_KK->close(); my_system._LinSolver[Level]->_RESC->close(); #ifdef DEFAULT_PRINT_INFO std::cout << " GenMatRhs " << my_system.name() << ": assembled Level " << Level << " with " << my_system._LinSolver[Level]->_KK->m() << " dofs " << std::endl; #endif return; }
void GenMatRhsT(MultiLevelProblem &ml_prob) { SystemTwo & my_system = ml_prob.get_system<SystemTwo>("Eqn_T"); const unsigned Level = my_system.GetLevelToAssemble(); const double time = 0.; //======== ELEMENT MAPPING ======= const uint space_dim = ml_prob._ml_msh->GetDimension(); my_system._LinSolver[Level]->_KK->zero(); my_system._LinSolver[Level]->_RESC->zero(); // ========================================== Mesh *mymsh = ml_prob._ml_msh->GetLevel(Level); elem *myel = mymsh->el; const unsigned myproc = mymsh->processor_id(); // ========================================== // ========================================== {//BEGIN VOLUME //==== AUXILIARY ============== double* dphijdx_g = new double[space_dim]; double* dphiidx_g = new double[space_dim]; const uint mesh_vb = VV; const uint nel_e = ml_prob.GetMeshTwo()._off_el[mesh_vb][ml_prob.GetMeshTwo()._NoLevels*myproc+Level+1]; const uint nel_b = ml_prob.GetMeshTwo()._off_el[mesh_vb][ml_prob.GetMeshTwo()._NoLevels*myproc+Level]; for (uint iel=0; iel < (nel_e - nel_b); iel++) { CurrentElem<double> currelem(iel,myproc,Level,VV,&my_system,ml_prob.GetMeshTwo(),ml_prob.GetElemType(),mymsh); CurrentGaussPointBase & currgp = CurrentGaussPointBase::build(currelem,ml_prob.GetQuadratureRule(currelem.GetDim())); //=========INTERNAL QUANTITIES (unknowns of the equation) ========= CurrentQuantity Tempold(currgp); Tempold._qtyptr = my_system.GetUnknownQuantitiesVector()[0]; Tempold.VectWithQtyFillBasic(); Tempold.Allocate(); //=========EXTERNAL QUANTITIES (couplings) ===== //========= //DOMAIN MAPPING CurrentQuantity xyz(currgp); //no quantity xyz._dim = space_dim; xyz._FEord = MESH_MAPPING_FE; xyz._ndof = currelem.GetElemType(xyz._FEord)->GetNDofs(); xyz.Allocate(); currelem.Mat().zero(); currelem.Rhs().zero(); currelem.SetDofobjConnCoords(); currelem.SetElDofsBc(); currelem.ConvertElemCoordsToMappingOrd(xyz); Tempold.GetElemDofs(); //==================== const uint el_ngauss = ml_prob.GetQuadratureRule(currelem.GetDim()).GetGaussPointsNumber(); for (uint qp=0; qp< el_ngauss; qp++) { //======= "COMMON SHAPE PART"================== for (uint fe = 0; fe < QL; fe++) { currgp.SetPhiElDofsFEVB_g (fe,qp); currgp.SetDPhiDxezetaElDofsFEVB_g (fe,qp); } const double det = currgp.JacVectVV_g(xyz); const double dtxJxW_g = det*ml_prob.GetQuadratureRule(currelem.GetDim()).GetGaussWeight(qp); const double detb = det/el_ngauss; for (uint fe = 0; fe < QL; fe++) { currgp.SetDPhiDxyzElDofsFEVB_g (fe,qp); currgp.ExtendDphiDxyzElDofsFEVB_g(fe); } //======= end of the "COMMON SHAPE PART"================== Tempold.val_g(); for (uint i=0; i < Tempold._ndof/*the maximum number is for biquadratic*/; i++) { const double phii_g = currgp._phi_ndsQLVB_g[Tempold._FEord][i]; for (uint idim = 0; idim < space_dim; idim++) dphiidx_g[idim] = currgp._dphidxyz_ndsQLVB_g[Tempold._FEord][i+idim*Tempold._ndof]; //=========== FIRST ROW =============== currelem.Rhs()(i) += currelem.GetBCDofFlag()[i]*dtxJxW_g*( 7.*phii_g ) + (1-currelem.GetBCDofFlag()[i])*detb*(Tempold._val_dofs[i]); currelem.Mat()(i,i) += (1-currelem.GetBCDofFlag()[i])*detb; // Matrix Assemblying --------------------------- for (uint j=0; j<Tempold._ndof; j++) { double phij_g = currgp._phi_ndsQLVB_g[Tempold._FEord][j]; for (uint idim = 0; idim < space_dim; idim++) { dphijdx_g [idim] = currgp._dphidxyz_ndsQLVB_g[Tempold._FEord][j+idim*Tempold._ndof]; } double Lap_g = Math::dot(dphijdx_g,dphiidx_g,space_dim); int ip1 = i + Tempold._ndof; int jp1 = j + Tempold._ndof; //============ FIRST ROW state delta T =============== //======= DIAGONAL ============================= currelem.Mat()(i,j) += currelem.GetBCDofFlag()[i]*dtxJxW_g*( Lap_g ); } //end j (col) } //end i (row) } // end of the quadrature point qp-loop currelem.Mat().print_scientific(std::cout); my_system._LinSolver[Level]->_KK->add_matrix(currelem.Mat(),currelem.GetDofIndices()); my_system._LinSolver[Level]->_RESC->add_vector(currelem.Rhs(),currelem.GetDofIndices()); } // end of element loop // ***************************************************************** delete [] dphijdx_g; delete [] dphiidx_g; }//END VOLUME my_system._LinSolver[Level]->_KK->close(); my_system._LinSolver[Level]->_RESC->close(); #ifdef DEFAULT_PRINT_INFO std::cout << " Matrix and RHS assembled for equation " << my_system.name() << " Level "<< Level << " dofs " << my_system._LinSolver[Level]->_KK->n() << std::endl; #endif return; }
/// This function assembles the matrix and the rhs: void GenMatRhsT(MultiLevelProblem &ml_prob){ //if we are just a function not inside a class, we have to retrieve ourselves... SystemTwo & my_system = ml_prob.get_system<SystemTwo>("Eqn_T"); const unsigned Level = my_system.GetLevelToAssemble(); // ========================================== Mesh *mymsh = ml_prob._ml_msh->GetLevel(Level); elem *myel = mymsh->el; const unsigned myproc = mymsh->processor_id(); //======== ELEMENT MAPPING ======= const uint space_dim = ml_prob._ml_msh->GetDimension(); //====== reference values ======================== const double IRe = 1./ml_prob.GetInputParser().get("Re"); const double IPr = 1./ml_prob.GetInputParser().get("Pr"); const double alphaT = ml_prob.GetInputParser().get("alphaT"); const double alphaL2 = ml_prob.GetInputParser().get("alphaL2"); const double alphaH1 = ml_prob.GetInputParser().get("alphaH1"); //==== AUXILIARY ============== std::vector<double> dphijdx_g(space_dim); std::vector<double> dphiidx_g(space_dim); my_system._LinSolver[Level]->_KK->zero(); my_system._LinSolver[Level]->_RESC->zero(); // ========================================== // ========================================== {//BEGIN VOLUME const uint mesh_vb = VV; const uint nel_b = ml_prob.GetMeshTwo()._off_el[mesh_vb][ml_prob.GetMeshTwo()._NoLevels*myproc+Level]; const uint nel_e = ml_prob.GetMeshTwo()._off_el[mesh_vb][ml_prob.GetMeshTwo()._NoLevels*myproc+Level+1]; // const uint nel_beg = mymsh->_elementOffset[myproc]; // const uint nel_end = mymsh->_elementOffset[myproc+1]; for (uint iel = 0; iel < (nel_e - nel_b); iel++) { // for (uint iel_two = nel_beg; iel_two < nel_end; iel_two++) { CurrentElem<double> currelem(iel,myproc,Level,VV,&my_system,ml_prob.GetMeshTwo(),ml_prob.GetElemType(),mymsh); CurrentGaussPointBase & currgp = CurrentGaussPointBase::build(currelem,ml_prob.GetQuadratureRule(currelem.GetDim())); //=========INTERNAL QUANTITIES (unknowns of the equation) ========= CurrentQuantity Tempold(currgp); Tempold._SolName = "Qty_Temperature"; Tempold._qtyptr = ml_prob.GetQtyMap().GetQuantity("Qty_Temperature"); Tempold.VectWithQtyFillBasic(); Tempold.Allocate(); //==================================== CurrentQuantity Tlift(currgp); Tlift._SolName = "Qty_TempLift"; Tlift._qtyptr = ml_prob.GetQtyMap().GetQuantity("Qty_TempLift"); Tlift.VectWithQtyFillBasic(); Tlift.Allocate(); //===================================== CurrentQuantity TAdj(currgp); TAdj._SolName = "Qty_TempAdj"; TAdj._qtyptr = ml_prob.GetQtyMap().GetQuantity("Qty_TempAdj"); TAdj.VectWithQtyFillBasic(); TAdj.Allocate(); //=========EXTERNAL QUANTITIES (couplings) ===== //========= //DOMAIN MAPPING CurrentQuantity xyz(currgp); //no quantity xyz._dim = space_dim; xyz._FEord = MESH_MAPPING_FE; xyz._ndof = currelem.GetElemType(xyz._FEord)->GetNDofs(); xyz.Allocate(); //================== CurrentQuantity velX(currgp); velX._SolName = "Qty_Velocity0"; velX._qtyptr = ml_prob.GetQtyMap().GetQuantity("Qty_Velocity0"); velX.VectWithQtyFillBasic(); velX.Allocate(); //================== CurrentQuantity velY(currgp); velY._SolName = "Qty_Velocity1"; velY._qtyptr = ml_prob.GetQtyMap().GetQuantity("Qty_Velocity1"); velY.VectWithQtyFillBasic(); velY.Allocate(); //===============Tdes===================== CurrentQuantity Tdes(currgp); Tdes._SolName = "Qty_TempDes"; Tdes._dim = Tempold._dim; Tdes._FEord = Tempold._FEord; Tdes._ndof = Tempold._ndof; Tdes.Allocate(); // ========================================== // ========================================== currelem.Mat().zero(); currelem.Rhs().zero(); currelem.SetDofobjConnCoords(); currelem.SetElDofsBc(); Tempold.GetElemDofs(); Tlift.GetElemDofs(); TAdj.GetElemDofs(); velX.GetElemDofs(); velY.GetElemDofs(); TempDesired(Tdes,currelem); currelem.ConvertElemCoordsToMappingOrd(xyz); xyz.SetElemAverage(); int domain_flag = ElFlagControl(xyz._el_average,ml_prob._ml_msh); //==================== const uint el_ngauss = ml_prob.GetQuadratureRule(currelem.GetDim()).GetGaussPointsNumber(); for (uint qp=0; qp< el_ngauss; qp++) { //======= "COMMON SHAPE PART"================== for (uint fe = 0; fe < QL; fe++) { currgp.SetPhiElDofsFEVB_g (fe,qp); currgp.SetDPhiDxezetaElDofsFEVB_g (fe,qp); } const double det = currgp.JacVectVV_g(xyz); const double dtxJxW_g = det*ml_prob.GetQuadratureRule(currelem.GetDim()).GetGaussWeight(qp); const double detb = det/el_ngauss; for (uint fe = 0; fe < QL; fe++) { currgp.SetDPhiDxyzElDofsFEVB_g (fe,qp); currgp.ExtendDphiDxyzElDofsFEVB_g(fe); } //======= end of the "COMMON SHAPE PART"================== Tempold.val_g(); Tlift.val_g(); TAdj.val_g(); velX.val_g(); velY.val_g(); Tdes.val_g(); for (uint i=0; i < Tempold._ndof; i++) { const double phii_g = currgp._phi_ndsQLVB_g[Tempold._FEord][i]; for (uint idim = 0; idim < space_dim; idim++) dphiidx_g[idim] = currgp._dphidxyz_ndsQLVB_g[Tempold._FEord][i+idim*Tempold._ndof]; //=========== FIRST ROW =============== currelem.Rhs()(i) += currelem.GetBCDofFlag()[i]*dtxJxW_g*( 0. ) + (1-currelem.GetBCDofFlag()[i])*detb*(Tempold._val_dofs[i]); currelem.Mat()(i,i) += (1-currelem.GetBCDofFlag()[i])*detb; //========= SECOND ROW (CONTROL) ===================== int ip1 = i + /* 1* */Tempold._ndof; //suppose that T' T_0 T_adj have the same order currelem.Rhs()(ip1) += currelem.GetBCDofFlag()[ip1]*dtxJxW_g*( + alphaT*domain_flag*(Tdes._val_g[0])*phii_g // T_d delta T_0 ) + (1-currelem.GetBCDofFlag()[ip1])*detb*(Tlift._val_dofs[i]); currelem.Mat()(ip1,ip1) += (1-currelem.GetBCDofFlag()[ip1])*detb; //======= THIRD ROW (ADJOINT) =================================== int ip2 = i + 2 * Tempold._ndof; //suppose that T' T_0 T_adj have the same order currelem.Rhs()(ip2) += currelem.GetBCDofFlag()[ip2]*dtxJxW_g*( + alphaT*domain_flag*(Tdes._val_g[0])*phii_g // T_d delta T' ) + (1-currelem.GetBCDofFlag()[ip2])*detb*(Tempold._val_dofs[i]); currelem.Mat()(ip2,ip2) += (1-currelem.GetBCDofFlag()[ip2])*detb; // Matrix Assemblying --------------------------- for (uint j=0; j<Tempold._ndof; j++) { double phij_g = currgp._phi_ndsQLVB_g[Tempold._FEord][j]; for (uint idim = 0; idim < space_dim; idim++) dphijdx_g[idim] = currgp._dphidxyz_ndsQLVB_g[Tempold._FEord][j+idim*Tempold._ndof]; double Lap_g = Math::dot(&dphijdx_g[0],&dphiidx_g[0],space_dim); double Advection = velX._val_g[0]*dphijdx_g[0] + velY._val_g[0]*dphijdx_g[1]; //Math::dot(&vel._val_g[0],&dphijdx_g[0],space_dim); int ip1 = i + Tempold._ndof; int jp1 = j + Tempold._ndof; int ip2 = i + 2*Tempold._ndof; int jp2 = j + 2*Tempold._ndof; // T T_0 T_adj // T X X O // T_0 // T_adj //============ FIRST ROW state delta T =============== //======= DIAGONAL ============================= currelem.Mat()(i,j) += currelem.GetBCDofFlag()[i]*dtxJxW_g*( + Advection*phii_g + IRe*IPr*Lap_g ); //=============================== //same operators for T and T_0 currelem.Mat()(i,jp1) += currelem.GetBCDofFlag()[i]*dtxJxW_g*( + Advection*phii_g + IRe*IPr*Lap_g ); //==================================== currelem.Mat()(i,jp2) += currelem.GetBCDofFlag()[i]*dtxJxW_g*( 0. ); //============= SECOND ROW (LIFTING) delta T_0 ============= //===== DIAGONAL =========================== currelem.Mat()(ip1,jp1) += currelem.GetBCDofFlag()[ip1]* dtxJxW_g*( + alphaL2*phij_g*phii_g //L_2 control norm + alphaH1*Lap_g //H_1 control norm + alphaT*domain_flag*(phij_g)*phii_g //T_0 delta T_0 //ADDED/////////////// ); //==================================== currelem.Mat()(ip1,j) += currelem.GetBCDofFlag()[ip1]* dtxJxW_g*( + alphaT*domain_flag*(phij_g)*phii_g //T' delta T_0 //ADDED/////////////// ); //==================================== currelem.Mat()(ip1,jp2) += currelem.GetBCDofFlag()[ip1]* dtxJxW_g*( -Advection*phii_g + IRe*IPr*Lap_g ); //============= THIRD ROW (ADJOINT) ============= //======= DIAGONAL ================== currelem.Mat()(ip2,jp2) += currelem.GetBCDofFlag()[ip2]* dtxJxW_g*( - Advection*phii_g //minus sign + IRe*IPr*Lap_g ); //==================================== currelem.Mat()(ip2,j) += currelem.GetBCDofFlag()[ip2]* dtxJxW_g*( + alphaT*domain_flag*(phij_g)*phii_g //T' delta T' ); //==================================== currelem.Mat()(ip2,jp1) += currelem.GetBCDofFlag()[ip2]* dtxJxW_g*( + alphaT*domain_flag*(phij_g)*phii_g //T_0 delta T' ///ADDED/////// ); } //end j (col) } //end i (row) } // end of the quadrature point qp-loop my_system._LinSolver[Level]->_KK->add_matrix(currelem.Mat(),currelem.GetDofIndices()); my_system._LinSolver[Level]->_RESC->add_vector(currelem.Rhs(),currelem.GetDofIndices()); } // end of element loop // ***************************************************************** }//END VOLUME my_system._LinSolver[Level]->_KK->close(); my_system._LinSolver[Level]->_RESC->close(); #ifdef DEFAULT_PRINT_INFO std::cout << " Matrix and RHS assembled for equation " << my_system.name() << " Level "<< Level << " dofs " << my_system._LinSolver[Level]->_KK->n() << std::endl; #endif return; }
//=================================================== /// This function assembles the matrix and the rhs: void GenMatRhsNS(MultiLevelProblem &ml_prob) { SystemTwo & my_system = ml_prob.get_system<SystemTwo>("Eqn_NS"); const unsigned Level = my_system.GetLevelToAssemble(); const uint _AdvPic_fl = 1; const uint _AdvNew_fl = 0; const uint _Stab_fl = 0; const double _Komp_fac = 0.; //========== GEOMETRIC ELEMENT ======== const uint space_dim = ml_prob._ml_msh->GetDimension(); //====== reference values ======================== //====== related to Quantities on which Operators act, and to the choice of the "LEADING" EQUATION Operator const double IRe = 1./ml_prob.GetInputParser().get("Re"); const double IFr = 1./ml_prob.GetInputParser().get("Fr"); //================================================ //================================================ //=======Operators @ gauss ======================= std::vector<double> dphijdx_g(space_dim); // ShapeDer(): used for Laplacian,Divergence, ..., associated to an Unknown Quantity std::vector<double> dphiidx_g(space_dim); // Test(): used for Laplacian,Advection,Divergence... associated to an Unknown Quantity std::vector<double> AdvRhs_g(space_dim); //Operator: Adv(u,u,phi) //================================================ my_system._LinSolver[Level]->_KK->zero(); my_system._LinSolver[Level]->_RESC->zero(); // ========================================== Mesh *mymsh = ml_prob._ml_msh->GetLevel(Level); elem *myel = mymsh->el; const unsigned myproc = mymsh->processor_id(); // ========================================== // ========================================== {//BEGIN VOLUME //======================== //======================== const uint mesh_vb = VV; const uint nel_e = ml_prob.GetMeshTwo()._off_el[mesh_vb][ml_prob.GetMeshTwo()._NoLevels*myproc+Level+1]; const uint nel_b = ml_prob.GetMeshTwo()._off_el[mesh_vb][ml_prob.GetMeshTwo()._NoLevels*myproc+Level]; for (int iel=0; iel < (nel_e - nel_b); iel++) { CurrentElem<double> currelem(iel,myproc,Level,VV,&my_system,ml_prob.GetMeshTwo(),ml_prob.GetElemType(),mymsh); CurrentGaussPointBase & currgp = CurrentGaussPointBase::build(currelem,ml_prob.GetQuadratureRule(currelem.GetDim())); //=========INTERNAL QUANTITIES (unknowns of the equation) ================== CurrentQuantity VelOldX(currgp); VelOldX._qtyptr = ml_prob.GetQtyMap().GetQuantity("Qty_Velocity0"); VelOldX._SolName = "Qty_Velocity0"; VelOldX.VectWithQtyFillBasic(); VelOldX.Allocate(); CurrentQuantity VelOldY(currgp); VelOldY._qtyptr = ml_prob.GetQtyMap().GetQuantity("Qty_Velocity1"); VelOldY._SolName = "Qty_Velocity1"; VelOldY.VectWithQtyFillBasic(); VelOldY.Allocate(); std::vector<CurrentQuantity*> VelOld_vec; VelOld_vec.push_back(&VelOldX); VelOld_vec.push_back(&VelOldY); const uint qtyzero_ord = VelOldX._FEord; const uint qtyzero_ndof = VelOldX._ndof; //same as Y //========= CurrentQuantity pressOld(currgp); pressOld._qtyptr = ml_prob.GetQtyMap().GetQuantity("Qty_Pressure"); pressOld._SolName = "Qty_Pressure"; pressOld.VectWithQtyFillBasic(); pressOld.Allocate(); const uint qtyone_ord = pressOld._FEord; const uint qtyone_ndof = pressOld._ndof; //order const uint qtyZeroToOne_DofOffset = VelOldX._ndof + VelOldY._ndof;//VelOld._ndof*VelOld._dim; //========= END INTERNAL QUANTITIES (unknowns of the equation) ================= //=========EXTERNAL QUANTITIES (couplings) ===== //========= //DOMAIN MAPPING CurrentQuantity xyz(currgp); //domain xyz._dim = space_dim; xyz._FEord = MESH_MAPPING_FE; xyz._ndof = currelem.GetElemType(xyz._FEord)->GetNDofs(); xyz.Allocate(); //other Physical constant Quantities //=======gravity================================== CurrentQuantity gravity(currgp); gravity._dim = space_dim; // gravity.Allocate(); CANNOT DO THIS NOW BECAUSE NOT ALL THE DATA FOR THE ALLOCATION ARE FILLED gravity._val_g.resize(gravity._dim); gravity._val_g[0] = ml_prob.GetInputParser().get("dirgx"); gravity._val_g[1] = ml_prob.GetInputParser().get("dirgy"); if ( space_dim == 3 ) gravity._val_g[2] = ml_prob.GetInputParser().get("dirgz"); //======================== //======================== currelem.Mat().zero(); currelem.Rhs().zero(); currelem.SetDofobjConnCoords(); currelem.SetElDofsBc(); currelem.ConvertElemCoordsToMappingOrd(xyz); //=======RETRIEVE the DOFS of the UNKNOWN QUANTITIES,i.e. MY EQUATION VelOldX.GetElemDofs(); VelOldY.GetElemDofs(); pressOld.GetElemDofs(); const uint el_ngauss = ml_prob.GetQuadratureRule(currelem.GetDim()).GetGaussPointsNumber(); for (uint qp = 0; qp < el_ngauss; qp++) { //=======here starts the "COMMON SHAPE PART"================== // the call of these things should be related to the Operator //also, the choice of the QuadratureRule should be dependent of the Involved Operators //and the FE orders on which these Operators act //these phi and dphi are used for the different stages: //BEFORE i: by the interpolation functions //INSIDE i: for the tEST functions and derivatives //INSIDE j: for the SHAPE functions and derivatives //again, it should be the Operator to decide what functions to be called, //for what FE ORDER and what DERIVATIVE ORDER //if we decide that the PREPARATION of the tEST and SHAPE //of a certain Unknown are COMMON TO ALL, //Then we must only concentrate on preparing the OTHER involved quantities in that Operator for (uint fe = 0; fe < QL; fe++) { currgp.SetPhiElDofsFEVB_g (fe,qp); currgp.SetDPhiDxezetaElDofsFEVB_g (fe,qp); } const double det = currgp.JacVectVV_g(xyz); const double dtxJxW_g = det*ml_prob.GetQuadratureRule(currelem.GetDim()).GetGaussWeight(qp); const double detb = det/el_ngauss; for (uint fe = 0; fe < QL; fe++) { currgp.SetDPhiDxyzElDofsFEVB_g (fe,qp); currgp.ExtendDphiDxyzElDofsFEVB_g(fe); } //=======end of the "COMMON SHAPE PART"================== //now we want to fill the element matrix and rhs with ONLY values AT GAUSS POINTS //we can divide the values at Gauss points into three parts: //1-constant values //2-values which depend on (i) //3-values which depend on (i,j) //1- can be used for filling both Ke and Fe //2- can be used to fill Fe and also Ke //3- can be used only for filling Ke //Here, before entering the (i,j) loop, you compute quantities that DO NOT depend on (i,j), //therefore the ELEMENT SUM, GAUSS SUM And tEST/SHAPE sums have ALL been performed //but, these quantities depend on idim and jdim, because they are involved in multiplications with tEST and SHAPE functions //Internal Quantities VelOldX.val_g(); VelOldX.grad_g(); VelOldY.val_g(); VelOldY.grad_g(); //Advection all VelOld for (uint idim=0; idim<space_dim; idim++) { AdvRhs_g[idim]=0.;} for (uint idim=0; idim<space_dim; idim++) { for (uint b=0; b<space_dim; b++) { AdvRhs_g[idim] += VelOld_vec[b]->_val_g[0]*VelOld_vec[idim]->_grad_g[0][b]; } } // grad is [ivar][idim], i.e. [u v w][x y z] //Divergence VelOld double Div_g=0.; for (uint idim=0; idim<space_dim; idim++) Div_g += VelOld_vec[idim]->_grad_g[0][idim]; //============================================================== //========= FILLING ELEMENT MAT/RHS (i loop) ==================== //============================================================== // TODO according to the order we should switch DIM loop and DOF loop for (uint i=0; i<qtyzero_ndof; i++) { //======="COMMON tEST PART for QTYZERO": func and derivative, of the QTYZERO FE ORD ========== const double phii_g = currgp._phi_ndsQLVB_g[qtyzero_ord][i]; for (uint idim=0; idim<space_dim; idim++) dphiidx_g[idim] = currgp._dphidxyz_ndsQLVB_g[qtyzero_ord][i+idim*qtyzero_ndof]; //======= END "COMMON tEST PART for QTYZERO" ========== for (uint idim=0; idim<space_dim; idim++) { const uint irowq=i+idim*qtyzero_ndof; // (i): dof of the tEST function //(idim): component of the tEST function currelem.Rhs()(irowq) += currelem.GetBCDofFlag()[irowq]* dtxJxW_g*( + _AdvNew_fl* AdvRhs_g[idim]*phii_g // NONLIN + IFr*gravity._val_g[idim]*phii_g // gravity ) + (1-currelem.GetBCDofFlag()[irowq])*detb*VelOld_vec[idim]->_val_dofs[i] //Dirichlet bc ; } // end filling element rhs u for (uint idim=0; idim<space_dim; idim++) { // filling diagonal for Dirichlet bc const uint irowq = i+idim*qtyzero_ndof; currelem.Mat()(irowq,irowq) += (1-currelem.GetBCDofFlag()[irowq])*detb; } // end filling diagonal for Dirichlet bc //============ QTYZERO x QTYZERO dofs matrix (A matrix) ============ for (uint j=0; j< qtyzero_ndof; j++) { //======="COMMON SHAPE PART for QTYZERO": func and derivative, of the QTYZERO FE ORD ========== // (j): dof of the SHAPE function double phij_g = currgp._phi_ndsQLVB_g[qtyzero_ord][j]; for (uint idim=0; idim<space_dim; idim++) dphijdx_g[idim] = currgp._dphidxyz_ndsQLVB_g[qtyzero_ord][j+idim*qtyzero_ndof]; //======= END "COMMON SHAPE PART for QTYZERO" ========== double Lap_g = Math::dot(&dphijdx_g[0],&dphiidx_g[0],space_dim); double Adv_g=0.; for (uint idim=0; idim<space_dim; idim++) Adv_g += VelOld_vec[idim]->_val_g[0] * dphijdx_g[idim]; // =Math::dot(&VelOld._val_g[0],dphijdx_g,space_dim); for (uint idim=0; idim<space_dim; idim++) { //filled in as 1-2-3 // 4-5-6 // 7-8-9 int irowq = i+idim*qtyzero_ndof; //(i) is still the dof of the tEST functions //(idim): component of the tEST functions currelem.Mat()(irowq,j+idim*qtyzero_ndof) // diagonal blocks [1-5-9] [idim(rows),idim(columns)] //(idim): component of the SHAPE functions += currelem.GetBCDofFlag()[irowq]* dtxJxW_g*( + _AdvPic_fl* Adv_g*phii_g //TODO NONLIN + _AdvNew_fl*phij_g*VelOld_vec[idim]->_grad_g[0][idim]*phii_g //TODO NONLIN + _AdvPic_fl*_Stab_fl* 0.5*Div_g*phij_g*phii_g //TODO NONLIN + IRe*( dphijdx_g[idim]*dphiidx_g[idim] + Lap_g) ); int idimp1=(idim+1)%space_dim; // block +1 [2-6-7] [idim(rows),idim+1(columns)] //(idimp1): component of the SHAPE functions currelem.Mat()(irowq,j+idimp1*qtyzero_ndof) += currelem.GetBCDofFlag()[irowq]* dtxJxW_g*( _AdvNew_fl*phij_g*VelOld_vec[idim]->_grad_g[0][idimp1]*phii_g //TODO NONLIN + IRe*( dphijdx_g[idim]*dphiidx_g[idimp1]) ); } } //============ END QTYZERO x QTYZERO dofs matrix (A matrix) ============ //============ QTYZERO x QTYONE dofs matrix (B^T matrix) // ( p*div(v) ) (NS eq) ============ for (uint j=0; j<qtyone_ndof; j++) { //======="COMMON SHAPE PART for QTYONE" ================== const double psij_g = currgp._phi_ndsQLVB_g[qtyone_ord][j]; //======="COMMON SHAPE PART for QTYONE" - END ============ const int jclml = j + qtyZeroToOne_DofOffset; for (uint idim=0; idim<space_dim; idim++) { uint irowq = i+idim*qtyzero_ndof; currelem.Mat()(irowq,jclml) += currelem.GetBCDofFlag()[irowq]* dtxJxW_g*(-psij_g*dphiidx_g[idim]); /** (-1.)*/ } } //============ END QTYZERO x QTYONE dofs matrix (B^T matrix) ============ if (i < qtyone_ndof) { //======="COMMON tEST PART for QTYONE" ============ double psii_g = currgp._phi_ndsQLVB_g[qtyone_ord][i]; //======= "COMMON tEST PART for QTYONE" - END ============ const uint irowl = i + qtyZeroToOne_DofOffset; currelem.Rhs()(irowl)=0.; // rhs // Mat()(irowl,j+space_dim*qtyzero_ndof) += (1./dt)*dtxJxW_g*(psii_g*psij_g)*_Komp_fac/dt; //no bc here (KOMP dp/dt=rho*div) for (uint j=0; j<qtyzero_ndof; j++) { // B element matrix q*div(u) //======="COMMON SHAPE PART for QTYZERO" ================== for (uint idim=0; idim<space_dim; idim++) dphijdx_g[idim] = currgp._dphidxyz_ndsQLVB_g[qtyzero_ord][j+idim*qtyzero_ndof]; //======="COMMON SHAPE PART for QTYZERO" - END ============ for (uint idim=0; idim<space_dim; idim++) currelem.Mat()(irowl,j+idim*qtyzero_ndof) += -/*(1./dt)**/dtxJxW_g*psii_g*dphijdx_g[idim]; } } // end pressure eq (cont) } //=================================================================== //========= END FILLING ELEMENT MAT/RHS (i loop) ===================== //=================================================================== } //============================================================== //================== END GAUSS LOOP (qp loop) ====================== //============================================================== /// Add element matrix and rhs to the global ones. my_system._LinSolver[Level]->_KK->add_matrix(currelem.Mat(),currelem.GetDofIndices()); my_system._LinSolver[Level]->_RESC->add_vector(currelem.Rhs(),currelem.GetDofIndices()); } // end of element loop }//END VOLUME my_system._LinSolver[Level]->_KK->close(); my_system._LinSolver[Level]->_RESC->close(); #ifdef DEFAULT_PRINT_INFO std::cout << " GenMatRhs " << my_system.name() << ": assembled Level " << Level << " with " << my_system._LinSolver[Level]->_KK->m() << " dofs" << std::endl; #endif return; }
void GenMatRhsNSAD(MultiLevelProblem &ml_prob) { SystemTwo & my_system = ml_prob.get_system<SystemTwo>("Eqn_NSAD"); const unsigned Level = my_system.GetLevelToAssemble(); // ========= parameters const double alphaVel = ml_prob.GetInputParser().get("alphaVel"); const double IRe = 1./ml_prob.GetInputParser().get("Re"); //=========== Operators double dphijdx_g[DIMENSION]; double dphiidx_g[DIMENSION]; double curlxiXB_g3D[3]; // //======== GEOMETRICAL ELEMENT ======= const uint space_dim = ml_prob._ml_msh->GetDimension(); my_system._LinSolver[Level]->_KK->zero(); my_system._LinSolver[Level]->_RESC->zero(); // ========================================== Mesh *mymsh = ml_prob._ml_msh->GetLevel(Level); elem *myel = mymsh->el; const unsigned myproc = mymsh->processor_id(); // ========================================== // ========================================== {//BEGIN VOLUME const uint mesh_vb = VV; const uint nel_e = ml_prob.GetMeshTwo()._off_el[mesh_vb][ml_prob.GetMeshTwo()._NoLevels*myproc+Level+1]; const uint nel_b = ml_prob.GetMeshTwo()._off_el[mesh_vb][ml_prob.GetMeshTwo()._NoLevels*myproc+Level]; for (uint iel=0; iel < (nel_e - nel_b); iel++) { CurrentElem currelem(iel,myproc,Level,VV,&my_system,ml_prob.GetMeshTwo(),ml_prob.GetElemType(),mymsh); CurrentGaussPointBase & currgp = CurrentGaussPointBase::build(currelem,ml_prob.GetQrule(currelem.GetDim())); //=========INTERNAL QUANTITIES (unknowns of the equation) ================== CurrentQuantity VelAdjOldX(currgp); VelAdjOldX._qtyptr = ml_prob.GetQtyMap().GetQuantity("Qty_VelocityAdj0"); VelAdjOldX.VectWithQtyFillBasic(); VelAdjOldX.Allocate(); CurrentQuantity VelAdjOldY(currgp); VelAdjOldY._qtyptr = ml_prob.GetQtyMap().GetQuantity("Qty_VelocityAdj1"); VelAdjOldY.VectWithQtyFillBasic(); VelAdjOldY.Allocate(); CurrentQuantity VelAdjOldZ(currgp); VelAdjOldZ._qtyptr = ml_prob.GetQtyMap().GetQuantity("Qty_VelocityAdj2"); VelAdjOldZ.VectWithQtyFillBasic(); VelAdjOldZ.Allocate(); std::vector<CurrentQuantity*> VelAdjOld_vec; VelAdjOld_vec.push_back(&VelAdjOldX); VelAdjOld_vec.push_back(&VelAdjOldY); VelAdjOld_vec.push_back(&VelAdjOldZ); CurrentQuantity PressAdjOld(currgp); PressAdjOld._qtyptr = ml_prob.GetQtyMap().GetQuantity("Qty_PressureAdj"); PressAdjOld.VectWithQtyFillBasic(); PressAdjOld.Allocate(); //========= END INTERNAL QUANTITIES (unknowns of the equation) ================= //=========EXTERNAL QUANTITIES (couplings) ===== //========= DOMAIN MAPPING CurrentQuantity xyz(currgp); xyz._dim = space_dim; xyz._FEord = MESH_MAPPING_FE; xyz._ndof = currelem.GetElemType(xyz._FEord)->GetNDofs(); xyz.Allocate(); CurrentQuantity VelX(currgp); VelX._qtyptr = ml_prob.GetQtyMap().GetQuantity("Qty_Velocity0"); VelX.VectWithQtyFillBasic(); VelX.Allocate(); CurrentQuantity VelY(currgp); VelY._qtyptr = ml_prob.GetQtyMap().GetQuantity("Qty_Velocity1"); VelY.VectWithQtyFillBasic(); VelY.Allocate(); CurrentQuantity VelZ(currgp); VelZ._qtyptr = ml_prob.GetQtyMap().GetQuantity("Qty_Velocity2"); VelZ.VectWithQtyFillBasic(); VelZ.Allocate(); std::vector<CurrentQuantity*> Vel_vec; Vel_vec.push_back(&VelX); Vel_vec.push_back(&VelY); Vel_vec.push_back(&VelZ); CurrentQuantity VelDesX(currgp); VelDesX._dim = 1; VelDesX._FEord = VelX._FEord; VelDesX._ndof = VelX._ndof; VelDesX.Allocate(); CurrentQuantity VelDesY(currgp); VelDesY._dim = 1; VelDesY._FEord = VelX._FEord; VelDesY._ndof = VelX._ndof; VelDesY.Allocate(); CurrentQuantity VelDesZ(currgp); VelDesZ._dim = 1; VelDesZ._FEord = VelX._FEord; VelDesZ._ndof = VelX._ndof; VelDesZ.Allocate(); std::vector<CurrentQuantity*> VelDes_vec; VelDes_vec.push_back(&VelDesX); VelDes_vec.push_back(&VelDesY); VelDes_vec.push_back(&VelDesZ); CurrentQuantity BhomX(currgp); BhomX._qtyptr = ml_prob.GetQtyMap().GetQuantity("Qty_MagnFieldHom0"); BhomX.VectWithQtyFillBasic(); BhomX.Allocate(); CurrentQuantity BhomY(currgp); BhomY._qtyptr = ml_prob.GetQtyMap().GetQuantity("Qty_MagnFieldHom1"); BhomY.VectWithQtyFillBasic(); BhomY.Allocate(); CurrentQuantity BhomZ(currgp); BhomZ._qtyptr = ml_prob.GetQtyMap().GetQuantity("Qty_MagnFieldHom2"); BhomZ.VectWithQtyFillBasic(); BhomZ.Allocate(); std::vector<CurrentQuantity*> Bhom_vec; Bhom_vec.push_back(&BhomX); Bhom_vec.push_back(&BhomY); Bhom_vec.push_back(&BhomZ); //Bhom only to retrieve the dofs CurrentQuantity BextX(currgp); BextX._qtyptr = ml_prob.GetQtyMap().GetQuantity("Qty_MagnFieldExt0"); BextX.VectWithQtyFillBasic(); BextX.Allocate(); CurrentQuantity BextY(currgp); BextY._qtyptr = ml_prob.GetQtyMap().GetQuantity("Qty_MagnFieldExt1"); BextY.VectWithQtyFillBasic(); BextY.Allocate(); CurrentQuantity BextZ(currgp); BextZ._qtyptr = ml_prob.GetQtyMap().GetQuantity("Qty_MagnFieldExt2"); BextZ.VectWithQtyFillBasic(); BextZ.Allocate(); std::vector<CurrentQuantity*> Bext_vec; Bext_vec.push_back(&BextX); Bext_vec.push_back(&BextY); Bext_vec.push_back(&BextZ); //========= auxiliary, must be AFTER Bhom! //TODO this doesnt have any associated quantity! CurrentQuantity Bmag(currgp); //total Bmag._dim = Bhom_vec.size(); Bmag._FEord = BhomX._FEord; Bmag._ndof = BhomX._ndof; Bmag.Allocate(); //=============== CurrentQuantity BhomAdjX(currgp); BhomAdjX._qtyptr = ml_prob.GetQtyMap().GetQuantity("Qty_MagnFieldHomAdj0"); BhomAdjX.VectWithQtyFillBasic(); BhomAdjX.Allocate(); CurrentQuantity BhomAdjY(currgp); BhomAdjY._qtyptr = ml_prob.GetQtyMap().GetQuantity("Qty_MagnFieldHomAdj1"); BhomAdjY.VectWithQtyFillBasic(); BhomAdjY.Allocate(); CurrentQuantity BhomAdjZ(currgp); BhomAdjZ._qtyptr = ml_prob.GetQtyMap().GetQuantity("Qty_MagnFieldHomAdj2"); BhomAdjZ.VectWithQtyFillBasic(); BhomAdjZ.Allocate(); std::vector<CurrentQuantity*> BhomAdj_vec; BhomAdj_vec.push_back(&BhomAdjX); BhomAdj_vec.push_back(&BhomAdjY); BhomAdj_vec.push_back(&BhomAdjZ); CurrentQuantity BhomAdj_vecQuant(currgp); //without quantity, nor equation BhomAdj_vecQuant._dim = BhomAdj_vec.size(); BhomAdj_vecQuant._FEord = BhomAdj_vec[0]->_FEord; BhomAdj_vecQuant._ndof = BhomAdj_vec[0]->_ndof; BhomAdj_vecQuant.Allocate(); //========= END EXTERNAL QUANTITIES ================= currelem.Mat().zero(); currelem.Rhs().zero(); currelem.SetDofobjConnCoords(); currelem.ConvertElemCoordsToMappingOrd(xyz); currelem.SetElDofsBc(); for (uint idim=0; idim < space_dim; idim++) { VelAdjOld_vec[idim]->GetElemDofs(); Vel_vec[idim]->GetElemDofs(); BhomAdj_vec[idim]->GetElemDofs(); Bhom_vec[idim]->GetElemDofs(); Bext_vec[idim]->GetElemDofs(); VelDesired(&ml_prob,*VelDes_vec[idim],currelem,idim); } BhomAdj_vecQuant.GetElemDofs(BhomAdj_vec); //this must be AFTER filling the scalar components PressAdjOld.GetElemDofs(); //======SUM Bhom and Bext //from now on, you'll only use Bmag //Bmag,Bext and Bhom must have the same orders! Math::zeroN(&Bmag._val_dofs[0],Bmag._dim*Bmag._ndof); for (uint ivarq=0; ivarq < Bmag._dim; ivarq++) { //ivarq is like idim for (uint d=0; d < Bmag._ndof; d++) { const uint indxq = d + ivarq*Bmag._ndof; Bmag._val_dofs[indxq] = Bext_vec[ivarq]->_val_dofs[d] + Bhom_vec[ivarq]->_val_dofs[d]; } } //======= ///optimal control xyz.SetElemAverage(); int el_flagdom = ElFlagControl(xyz._el_average,ml_prob._ml_msh); const uint el_ngauss = ml_prob.GetQrule(currelem.GetDim()).GetGaussPointsNumber(); for (uint qp = 0; qp < el_ngauss; qp++) { //=======here starts the "COMMON SHAPE PART"================== for (uint fe = 0; fe < QL; fe++) { currgp.SetPhiElDofsFEVB_g (fe,qp); currgp.SetDPhiDxezetaElDofsFEVB_g (fe,qp); } const double det = currgp.JacVectVV_g(xyz); //InvJac: is the same for both QQ and LL! const double dtxJxW_g = det*ml_prob.GetQrule(currelem.GetDim()).GetGaussWeight(qp); const double detb = det/el_ngauss; for (uint fe = 0; fe < QL; fe++) { currgp.SetDPhiDxyzElDofsFEVB_g (fe,qp); currgp.ExtendDphiDxyzElDofsFEVB_g(fe); } //=======end of the "COMMON SHAPE PART"================== BhomAdj_vecQuant.curl_g(); Bmag.val_g(); for (uint idim=0; idim < space_dim; idim++) { VelAdjOld_vec[idim]->val_g(); VelDes_vec[idim]->val_g(); Vel_vec[idim]->val_g(); Vel_vec[idim]->grad_g(); } //vector product Math::extend(&Bmag._val_g[0],&Bmag._val_g3D[0],space_dim); Math::cross(&BhomAdj_vecQuant._curl_g3D[0],&Bmag._val_g3D[0],curlxiXB_g3D); //============================================================== //========= FILLING ELEMENT MAT/RHS (i loop) ==================== //============================================================== for (uint i = 0; i < VelAdjOldX._ndof; i++) { const double phii_g = currgp._phi_ndsQLVB_g[VelAdjOldX._FEord][i]; for (uint idim=0; idim<space_dim; idim++) dphiidx_g[idim]= currgp._dphidxyz_ndsQLVB_g[VelAdjOldX._FEord][i+idim*VelAdjOldX._ndof]; for (uint idim=0; idim<space_dim; idim++) { const uint irowq=i+idim*VelAdjOldX._ndof; //quadratic rows index currelem.Rhs()(irowq) += currelem.GetBCDofFlag()[irowq]*dtxJxW_g*( - curlxiXB_g3D[idim]*phii_g //this is due to the variation of velocity in the MAGNETIC ADVECTION, so it is due to a NONLINEAR COUPLING "u times B", "MY_STATE times OTHER_STATE" - alphaVel*el_flagdom*(Vel_vec[idim]->_val_g[0] - VelDes_vec[idim]->_val_g[0])*phii_g //this is the dependence that counts ) + (1-currelem.GetBCDofFlag()[irowq])*detb*VelAdjOld_vec[idim]->_val_dofs[i]; //Dirichlet bc } for (uint idim=0; idim<space_dim; idim++) { // filling diagonal for Dirichlet bc const uint irowq = i+idim*VelAdjOldX._ndof; currelem.Mat()(irowq,irowq) += (1-currelem.GetBCDofFlag()[irowq])*detb; }// end filling diagonal for Dirichlet bc for (uint j=0; j<VelAdjOldX._ndof; j++) {// A element matrix double phij_g = currgp._phi_ndsQLVB_g[VelAdjOldX._FEord][j]; for (uint idim=0; idim<space_dim; idim++) dphijdx_g[idim] = currgp._dphidxyz_ndsQLVB_g[VelAdjOldX._FEord][j+idim*VelAdjOldX._ndof]; double Lap_g = Math::dot(dphijdx_g,dphiidx_g,space_dim); double Advphii_g = 0.; for (uint idim=0; idim<space_dim; idim++) Advphii_g += Vel_vec[idim]->_val_g[0]*dphiidx_g[idim]; //TODO can put it outside for (uint idim=0; idim<space_dim; idim++) { //filled in as 1-2-3 // 4-5-6 // 7-8-9 int irowq = i+idim*VelAdjOldX._ndof; // diagonal blocks [1-5-9] currelem.Mat()(irowq,j+idim*VelAdjOldX._ndof) += currelem.GetBCDofFlag()[irowq]*dtxJxW_g*( + IRe*(dphijdx_g[idim]*dphiidx_g[idim] + Lap_g) //Adjoint of D is D, Adjoint of Laplacian is Laplacian + phij_g*phii_g*/*dveldx_g*/Vel_vec[idim]->_grad_g[0][idim] //Adjoint of Advection 1 delta(u) DOT grad(u): adj of nonlinear stuff has 2 TERMS (well, not always) + phij_g*Advphii_g //Adjoint of Advection 2 u DOT grad (delta(u)): adj of nonlinear stuff has 2 TERMS ); // block +1 [2-6-7] int idimp1=(idim+1)%space_dim; currelem.Mat()(irowq,j+idimp1*VelAdjOldX._ndof) += currelem.GetBCDofFlag()[irowq]*dtxJxW_g*( + IRe*(dphijdx_g[idim]*dphiidx_g[idimp1]) + phij_g*phii_g*/*dveldx_g*/Vel_vec[idimp1]->_grad_g[0][idim] ); #if (DIMENSION==3) // block +2 [3-4-8] int idimp2=(idim+2)%space_dim; currelem.Mat()(irowq,j+idimp2*VelAdjOldX._ndof) += currelem.GetBCDofFlag()[irowq]*dtxJxW_g*( + IRe*(dphijdx_g[idim]*dphiidx_g[idimp2]) + phij_g*phii_g*/*dveldx_g*/Vel_vec[idimp2]->_grad_g[0][idim] ); #endif } } // end A element matrix for (uint j=0; j<PressAdjOld._ndof; j++) {// B^T element matrix ( p*div(v) ) (NS eq) const double psij_g = currgp._phi_ndsQLVB_g[PressAdjOld._FEord][j]; const int jclml= j + space_dim*VelAdjOldX._ndof; for (uint idim=0; idim<space_dim; idim++) { uint irowq = i+idim*VelAdjOldX._ndof; currelem.Mat()(irowq,jclml) += currelem.GetBCDofFlag()[irowq]*dtxJxW_g*(-psij_g*dphiidx_g[idim]); } } // end B^T element matrix if (i<PressAdjOld._ndof) {// pressure equation (KOMP dp/dt=rho*div) double psii_g = currgp._phi_ndsQLVB_g[PressAdjOld._FEord][i]; const uint irowl = i+space_dim*VelAdjOldX._ndof; //vertical offset currelem.Rhs()(irowl)=0.; // rhs for (uint j=0; j<VelAdjOldX._ndof; j++) { // B element matrix q*div(u) for (uint idim=0; idim<space_dim; idim++) dphijdx_g[idim] = currgp._dphidxyz_ndsQLVB_g[VelAdjOldX._FEord][j+idim*VelAdjOldX._ndof]; for (uint idim=0; idim<space_dim; idim++) currelem.Mat()(irowl,j+idim*VelAdjOldX._ndof) += -dtxJxW_g*psii_g*dphijdx_g[idim]; } } // end pressure eq (cont) } //=================================================================== //========= END FILLING ELEMENT MAT/RHS (i loop) ===================== //=================================================================== } // end element gaussian integration loop /// Add element matrix and rhs to the global ones. my_system._LinSolver[Level]->_KK->add_matrix(currelem.Mat(),currelem.GetDofIndices()); my_system._LinSolver[Level]->_RESC->add_vector(currelem.Rhs(),currelem.GetDofIndices()); } // end of element loop }//END VOLUME my_system._LinSolver[Level]->_KK->close(); my_system._LinSolver[Level]->_RESC->close(); #ifdef DEFAULT_PRINT_INFO std::cout << " GenMatRhs " << my_system.name() << ": assembled Level " << Level << " with " << my_system._LinSolver[Level]->_KK->m() << " dofs" << std::endl; #endif return; }