コード例 #1
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;  
  
}
コード例 #2
0
ファイル: EqnNSAD.cpp プロジェクト: gcapodag/MyFEMuS
 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;
}