예제 #1
0
파일: EqnMHD.cpp 프로젝트: FeMTTU/femus
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;
}
예제 #2
0
파일: EqnNS.cpp 프로젝트: FeMTTU/femus
//===================================================
/// 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;
}
예제 #3
0
파일: EqnT.cpp 프로젝트: FeMTTU/femus
/// 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;
}
예제 #4
0
 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;
}