예제 #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
파일: Math.hpp 프로젝트: gcapodag/MyFEMuS
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;  
  
}
예제 #3
0
파일: EqnT.cpp 프로젝트: FeMTTU/femus
 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;
}
예제 #4
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;
}
예제 #5
0
파일: ex_time.cpp 프로젝트: FeMTTU/femus
//------------------------------------------------------------------------------------------------------------
void AssembleMatrixRes_VC(MultiLevelProblem &ml_prob) {

  TransientNonlinearImplicitSystem* mlPdeSys = & ml_prob.get_system<TransientNonlinearImplicitSystem>("Timedep");
  const unsigned level = mlPdeSys->GetLevelToAssemble();

  MultiLevelSolution *ml_sol			      = ml_prob._ml_sol;
  Solution*	 sol  	                          = ml_sol->GetSolutionLevel(level);
  LinearEquationSolver*  pdeSys	              = mlPdeSys->_LinSolver[level];
  const char* pdename                         = mlPdeSys->name().c_str();

  Mesh*		 msh    	   = ml_prob._ml_msh->GetLevel(level);
  elem*		 myel		   = msh->el;
  SparseMatrix*	 JAC	   = pdeSys->_KK;
  NumericVector* RES 	   = pdeSys->_RES;

  // data
  const unsigned dim = msh->GetDimension();
  const unsigned max_size = static_cast< unsigned >(ceil(pow(3, dim)));          // conservative: based on line3, quad9, hex27
  unsigned nel = msh->GetNumberOfElements();
  unsigned igrid = msh->GetLevel();
  unsigned iproc = msh->processor_id();
  
  // time dep data
  double dt = mlPdeSys->GetIntervalTime();
//   double theta = 0.5;

  //************** geometry (at dofs and quadrature points) *************************************  
  vector < vector < double > > coords_at_dofs(dim);
  unsigned coords_fe_type = BIQUADR_FE; // get the finite element type for "x", it is always 2 (LAGRANGE BIQUADRATIC)
  for (unsigned i = 0; i < coords_at_dofs.size(); i++)    coords_at_dofs[i].reserve(max_size);

  vector < double > coord_at_qp(dim);
  
  //************* shape functions (at dofs and quadrature points) **************************************  
  const int solType_max = BIQUADR_FE;  //biquadratic

  double weight_qp; // gauss point weight
  
  vector < vector < double > > phi_fe_qp(NFE_FAMS);
  vector < vector < double > > phi_x_fe_qp(NFE_FAMS);
  vector < vector < double > > phi_xx_fe_qp(NFE_FAMS);
 
  for(int fe=0; fe < NFE_FAMS; fe++) {  
        phi_fe_qp[fe].reserve(max_size);
      phi_x_fe_qp[fe].reserve(max_size*dim);
     phi_xx_fe_qp[fe].reserve(max_size*(3*(dim-1)));
   }

  
  //***************************************************  
  //********* WHOLE SET OF VARIABLES ****************** 
  //***************************************************  
  const unsigned int n_unknowns = mlPdeSys->GetSolPdeIndex().size();

  vector < std::string > Solname(n_unknowns);     Solname[0] = "u";
  vector < unsigned > SolPdeIndex(n_unknowns);
  vector < unsigned > SolIndex(n_unknowns);
  vector < unsigned int > SolFEType(n_unknowns);     //FEtype of each MultilevelSolution       
  vector < unsigned int > Sol_n_el_dofs(n_unknowns); //number of element dofs

  std::fill(Sol_n_el_dofs.begin(), Sol_n_el_dofs.end(), 0);

  for(unsigned ivar=0; ivar < n_unknowns; ivar++) {
    SolPdeIndex[ivar] = mlPdeSys->GetSolPdeIndex(  Solname[ivar].c_str() );
       SolIndex[ivar] = ml_sol->GetIndex         ( Solname[ivar].c_str() );
      SolFEType[ivar] = ml_sol->GetSolutionType  ( SolIndex[ivar]);
  }
  
  //------------ quantities (at quadrature points) ---------------------
          vector<double>        sol_qp(n_unknowns);
          vector<double>    sol_old_qp(n_unknowns);
  vector< vector<double> > sol_grad_qp(n_unknowns);
  vector< vector<double> > sol_old_grad_qp(n_unknowns);
    
  std::fill(sol_qp.begin(), sol_qp.end(), 0.);
  std::fill(sol_old_qp.begin(), sol_old_qp.end(), 0.);
  for (unsigned  k = 0; k < n_unknowns; k++) {
        sol_grad_qp[k].resize(dim);
        std::fill(sol_grad_qp[k].begin(), sol_grad_qp[k].end(), 0.);
        sol_old_grad_qp[k].resize(dim);
        std::fill(sol_old_grad_qp[k].begin(), sol_old_grad_qp[k].end(), 0.);
    }

  //----------- quantities (at dof objects) ------------------------------
  vector < vector < double > >     sol_eldofs(n_unknowns);
  vector < vector < double > >     sol_old_eldofs(n_unknowns);
  for(int k=0; k<n_unknowns; k++) { sol_eldofs[k].reserve(max_size);
                                sol_old_eldofs[k].reserve(max_size);
   }
  
  //******** linear system *******************************************  
  vector < vector < int > > L2G_dofmap(n_unknowns);     for(int i = 0; i < n_unknowns; i++) { L2G_dofmap[i].reserve(max_size); }
            vector< int >   L2G_dofmap_AllVars; L2G_dofmap_AllVars.reserve( n_unknowns*max_size );
          
  vector< vector< double > > Res_el(n_unknowns);
  vector< vector< vector< double > > > Jac_el(n_unknowns);

   for(int i = 0; i < n_unknowns; i++) Res_el[i].reserve(max_size);

   for(int i = 0; i < n_unknowns; i++) {
     Jac_el[i].resize(n_unknowns);
     for(int j = 0; j < n_unknowns; j++) {
        Jac_el[i][j].reserve(max_size*max_size);
     }
   }
  
  // Set to zero all the entries of the matrix
  RES->zero();
  JAC->zero();
  
  
  const double deltat_term = 1.;
  const double lapl_term = 1.;
  const double delta_g_term = 1.;

  
  // *** element loop ***
  for (int iel = msh->_elementOffset[iproc]; iel < msh->_elementOffset[iproc+1]; iel++) {

    short unsigned ielGeom = msh->GetElementType(iel);    // element geometry type
    
    //******************** GEOMETRY ********************* 
    unsigned nDofx = msh->GetElementDofNumber(iel, coords_fe_type);       // number of coordinate element dofs
    for (int i = 0; i < dim; i++)  coords_at_dofs[i].resize(nDofx);
    // local storage of coordinates
    for (unsigned i = 0; i < nDofx; i++) {
      unsigned xDof  = msh->GetSolutionDof(i, iel, coords_fe_type);       // global to global mapping between coordinates node and coordinate dof

      for (unsigned jdim = 0; jdim < dim; jdim++) {
        coords_at_dofs[jdim][i] = (*msh->_topology->_Sol[jdim])(xDof);    // global extraction and local storage for the element coordinates
      }
    }
  //***************************************************  
    
  //all vars###################################################################  
  for (unsigned  k = 0; k < n_unknowns; k++) {
    unsigned  ndofs_unk = msh->GetElementDofNumber(iel, SolFEType[k]);
	   Sol_n_el_dofs[k] = ndofs_unk;
          sol_eldofs[k].resize(ndofs_unk);
      sol_old_eldofs[k].resize(ndofs_unk);
          L2G_dofmap[k].resize(ndofs_unk); 
    for (unsigned i = 0; i < ndofs_unk; i++) {
            unsigned solDof = msh->GetSolutionDof(i, iel, SolFEType[k]);                    // global to global mapping between solution node and solution dof 
                                                                                            // via local to global solution node
           sol_eldofs[k][i] = (*sol->_Sol[SolIndex[k]])(solDof);                            // global extraction and local storage for the solution
       sol_old_eldofs[k][i] = (*sol->_SolOld[SolIndex[k]])(solDof);                         // This is OLD in TIME, not in nonlinear loop
           L2G_dofmap[k][i] = pdeSys->GetSystemDof(SolIndex[k], SolPdeIndex[k], i, iel);    // global to global mapping between solution node and pdeSys dof
      }
    }
    
    
    unsigned nDof_AllVars = 0;
    for (unsigned  k = 0; k < n_unknowns; k++) { nDof_AllVars += Sol_n_el_dofs[k]; }
    // TODO COMPUTE MAXIMUM maximum number of element dofs for one scalar variable
    int nDof_max    =  0;   
      for (unsigned  k = 0; k < n_unknowns; k++)     {
          if(Sol_n_el_dofs[k] > nDof_max)    nDof_max = Sol_n_el_dofs[k];
       }
    
      for(int k = 0; k < n_unknowns; k++) {
      L2G_dofmap[k].resize(Sol_n_el_dofs[k]);

      Res_el[SolPdeIndex[k]].resize(Sol_n_el_dofs[k]);
      memset(& Res_el[SolPdeIndex[k]][0], 0., Sol_n_el_dofs[k] * sizeof(double) );


      Jac_el[SolPdeIndex[k]][SolPdeIndex[k]].resize(Sol_n_el_dofs[k] * Sol_n_el_dofs[k]);
      memset(& Jac_el[SolPdeIndex[k]][SolPdeIndex[k]][0], 0., Sol_n_el_dofs[k] * Sol_n_el_dofs[k] * sizeof(double));
    }

  //all vars###################################################################    

      // *** quadrature loop ***
      for(unsigned ig = 0; ig < ml_prob.GetQuadratureRule(ielGeom).GetGaussPointsNumber(); ig++) {
          
      // *** get gauss point weight, test function and test function partial derivatives ***
      for(int fe=0; fe < NFE_FAMS; fe++) {
         msh->_finiteElement[ielGeom][fe]->Jacobian(coords_at_dofs,ig,weight_qp,phi_fe_qp[fe],phi_x_fe_qp[fe],phi_xx_fe_qp[fe]);
      }
      //HAVE TO RECALL IT TO HAVE BIQUADRATIC JACOBIAN
         msh->_finiteElement[ielGeom][coords_fe_type]->Jacobian(coords_at_dofs,ig,weight_qp,phi_fe_qp[coords_fe_type],phi_x_fe_qp[coords_fe_type],phi_xx_fe_qp[coords_fe_type]);

   //========= fill gauss value quantities ==================   
   std::fill(sol_qp.begin(), sol_qp.end(), 0.);
   std::fill(sol_old_qp.begin(), sol_old_qp.end(), 0.);
   for (unsigned  k = 0; k < n_unknowns; k++) { std::fill(sol_grad_qp[k].begin(), sol_grad_qp[k].end(), 0.); 
                                                std::fill(sol_old_grad_qp[k].begin(), sol_old_grad_qp[k].end(), 0.);
                                            }
    
    for (unsigned  k = 0; k < n_unknowns; k++) {
	for (unsigned i = 0; i < Sol_n_el_dofs[k]; i++) {
	                                                         sol_qp[k]    +=     sol_eldofs[k][i] *   phi_fe_qp[SolFEType[k]][i];
	                                                     sol_old_qp[k]    += sol_old_eldofs[k][i] *   phi_fe_qp[SolFEType[k]][i];
                   for (unsigned d = 0; d < dim; d++) {      sol_grad_qp[k][d] +=     sol_eldofs[k][i] * phi_x_fe_qp[SolFEType[k]][i * dim + d]; 
                                                         sol_old_grad_qp[k][d] += sol_old_eldofs[k][i] * phi_x_fe_qp[SolFEType[k]][i * dim + d]; 
                                     }
       }        
    }
 
  //========= fill gauss value quantities ==================
         
	// *** phi_i loop ***
	for(unsigned i = 0; i < nDof_max; i++) {

    //BEGIN RESIDUALS A block ===========================
	    double Lap_rhs_i = 0.;
	    double Lap_old_rhs_i = 0.;
	    for(unsigned d = 0;  d < dim;  d++) {
	      Lap_rhs_i     += phi_x_fe_qp[SolFEType[0]][i * dim + d] *     sol_grad_qp[0][d];
	      Lap_old_rhs_i += phi_x_fe_qp[SolFEType[0]][i * dim + d] * sol_old_grad_qp[0][d];
	    }
	    Res_el[SolPdeIndex[0]][i] +=  - weight_qp * ( 
                       delta_g_term * Singularity::function(sol_qp[0]) * Singularity::g_vc(sol_qp[0])     * phi_fe_qp[ SolFEType[0] ][i]
                     - delta_g_term * Singularity::function(sol_qp[0]) * Singularity::g_vc(sol_old_qp[0]) * phi_fe_qp[ SolFEType[0] ][i]
                     + deltat_term * Singularity::function(sol_qp[0]) * dt                               * phi_fe_qp[ SolFEType[0] ][i]
                     + lapl_term *  dt * Lap_rhs_i
            );
    //END RESIDUALS A block ===========================


	    // *** phi_j loop ***
	    for(unsigned j = 0; j<nDof_max; j++) {
            
          double Lap_mat_i_j = 0.;
          for(unsigned d = 0; d < dim; d++) Lap_mat_i_j += phi_x_fe_qp[SolFEType[0]][i * dim + d] *
                                                           phi_x_fe_qp[SolFEType[0]][j * dim + d];


          Jac_el[SolPdeIndex[0]][SolPdeIndex[0]][i * Sol_n_el_dofs[0] + j] += weight_qp * (
                    + delta_g_term * phi_fe_qp[ SolFEType[0] ][i] * Singularity::derivative(  phi_fe_qp[ SolFEType[0] ][j] ) * phi_fe_qp[ SolFEType[0] ][j] * Singularity::g_vc( phi_fe_qp[ SolFEType[0] ][j] ) 
                    + delta_g_term * phi_fe_qp[ SolFEType[0] ][i] * Singularity::function  (  phi_fe_qp[ SolFEType[0] ][j] ) * Singularity::g_vc_derivative( phi_fe_qp[ SolFEType[0] ][j] ) * phi_fe_qp[ SolFEType[0] ][j] 
                    
                    - delta_g_term * phi_fe_qp[ SolFEType[0] ][i] * Singularity::derivative(  phi_fe_qp[ SolFEType[0] ][j] ) * phi_fe_qp[ SolFEType[0] ][j] * Singularity::g_vc( sol_old_qp[0] ) 
                    
                    + deltat_term * phi_fe_qp[ SolFEType[0] ][i] * Singularity::derivative(  phi_fe_qp[ SolFEType[0] ][j] ) * phi_fe_qp[ SolFEType[0] ][j] * dt 
                    + lapl_term * dt * Lap_mat_i_j  
                                                                                          );
	      
  	    }    //end phij loop

        
    }        //end phii loop
    
  }          // end gauss point loop

//--------------------------------------------------------------------------------------------------------
    //Sum the local matrices/vectors into the Global Matrix/Vector
    for(unsigned ivar=0; ivar < n_unknowns; ivar++) {
      RES->add_vector_blocked(Res_el[SolPdeIndex[ivar]],L2G_dofmap[ivar]);
      JAC->add_matrix_blocked(Jac_el[SolPdeIndex[ivar]][SolPdeIndex[ivar]],L2G_dofmap[ivar],L2G_dofmap[ivar]);
    }
    //--------------------------------------------------------------------------------------------------------
  } //end list of elements loop for each subdomain

  JAC->close();
  RES->close();
  // ***************** END ASSEMBLY *******************
}
예제 #6
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;
}
예제 #7
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;
}