problem.cpp

来自「FreeFem++可以生成高质量的有限元网格。可以用于流体力学」· C++ 代码 · 共 1,861 行 · 第 1/5 页

CPP
1,861
字号
// -*- Mode : c++ -*-//// SUMMARY  :      // USAGE    :        // ORG      : // AUTHOR   : Frederic Hecht// E-MAIL   : hecht@ann.jussieu.fr///*  This file is part of Freefem++  Freefem++ is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.  Freefem++  is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.  You should have received a copy of the GNU Lesser General Public License along with Freefem++; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */#include  <iostream>using namespace std;#include "rgraph.hpp"#include "error.hpp"#include "AFunction.hpp"//#include "lex.hpp"#include "MatriceCreuse_tpl.hpp"#include "Mesh3dn.hpp"#include "MeshPoint.hpp"#include "lgfem.hpp"#include "lgmesh3.hpp"#include "lgsolver.hpp"#include "problem.hpp"#include <set>basicAC_F0::name_and_type  CDomainOfIntegration::name_param[]= {    { "qft", &typeid(const Fem2D::QuadratureFormular *)},    { "qfe", &typeid(const Fem2D::QuadratureFormular1d *)},    { "qforder",&typeid(long)},    { "qfnbpT",&typeid(long)},    { "qfnbpE",&typeid(long)},    { "optimize",&typeid(bool)},    { "binside",&typeid(double)},    { "mortar",&typeid(bool)}};basicAC_F0::name_and_type  Problem::name_param[]= {  {  "init", &typeid(bool)},  {  "solver", &typeid(TypeSolveMat*)},  {  "eps", &typeid(double) },  {  "precon",&typeid(Polymorphic*)},   {  "dimKrylov",&typeid(long)},  {  "bmat",&typeid(Matrice_Creuse<R>* )},  {  "tgv",&typeid(double )},  {  "strategy",&typeid(long )},  {  "save",&typeid(string* )},  {  "cadna",&typeid(KN<double>*)},  {  "tolpivot", &typeid(double)},  {  "tolpivotsym", &typeid(double)},  {  "nbiter", &typeid(long)} // 12   };namespace Fem2D {void Check(const Opera &Op,int N,int  M) {   int err=0;   for (BilinearOperator::const_iterator l=Op.v.begin();l!=Op.v.end();l++)     {  // attention la fonction test donne la ligne        //  et la fonction test est en second             BilinearOperator::K ll(*l);       pair<int,int> jj(ll.first.first),ii(ll.first.second);       if (ii.first <0 || ii.first >= M) err++;       if (jj.first <0 || jj.first >= N) err++;            }   if (err) {     cout << "Check Bilinear Operator" << N << " " << M << endl;     for (BilinearOperator::const_iterator l=Op.v.begin();l!=Op.v.end();l++)       {  // attention la fonction test donne la ligne          //  et la fonction test est en second               BilinearOperator::K ll(*l);         pair<int,int> jj(ll.first.first),ii(ll.first.second);         cout << " +  " << jj.first << " " << jj.second << "*" << ii.first << " " << ii.second << endl;          }     ExecError("Check BilinearOperator N M");   } } void Check(const  BC_set * bc,int N) {   int err=0;   int kk=bc->bc.size();   for (int k=0;k<kk;k++)     {       pair<int,Expression> xx=bc->bc[k];       if (xx.first >= N) {          err++;         cerr << " Sorry : just " << N << " componant in FE space \n"              << "   and Boundary condition refere to " << xx.first << "+1 componant " << endl;       }     }   if (err)      ExecError("Incompatibility beetwen  boundary condition  and FE space"); }   void Check(const  Ftest * fl,int N) {   assert(fl);   int err=0;   Ftest::const_iterator kk= fl->v.end(),k;   int ii=0;   for (k=fl->v.begin();k<kk;k++)     {        ii++;       int j=k->first.first;       if (  j >= N) {          err++;         cerr << " Sorry : just " << N << " componant in FE space \n"              << " and linear var form  refere to " << j << "+1 componant (part " << ii << ")" << endl;       }     }   if (err)      ExecError("Incompatibility beetwen linear varf  and FE space"); } //---------------------------------------------------------------------------------------  template<class R>  void  Element_OpVF(MatriceElementairePleine<R,FESpace3> & mat,		     const FElement3 & Ku,const FElement3 & KKu,		     const FElement3 & Kv,const FElement3 & KKv,		     double * p,int ie,int iie, int label,void *bstack)  {    ffassert(0);   }    template<class R>  void  Element_OpVF(MatriceElementairePleine<R,FESpace> & mat,			const FElement & Ku,const FElement & KKu,			const FElement & Kv,const FElement & KKv,			double * p,int ie,int iie, int label,void *bstack)  {        pair<void *,double *> * bs=static_cast<pair<void *,double *> *>(bstack);       void * stack= bs->first;    double binside = *bs->second; // truc FH pour fluide de grad2 (decentrage bizard)    assert(mat.onFace); //   Finite Volume or discontinous Galerkine     assert(ie>=0 && ie < 3); //  int on edge     MeshPoint mp= *MeshPointStack(stack);    R ** copt = Stack_Ptr<R*>(stack,ElemMatPtrOffset);        bool same = &Ku == & Kv;    assert(same);     const Triangle & T  = Ku.T;    int nTonEdge =  &Ku == &KKu ? 1 : 2;     double cmean = 1./nTonEdge;        throwassert(&T == &Kv.T);    // const QuadratureFormular & FI = mat.FIT;    const QuadratureFormular1d & FIb = mat.FIE;    long npi;    R *a=mat.a;    R *pa=a;    long i,j;    long n= mat.n,m=mat.m,nx=n*m;    assert(nx<=mat.lga);    long N= Kv.N;    long M= Ku.N;        long mu=Ku.NbDoF();    long mmu=KKu.NbDoF();    long nv=Kv.NbDoF();    long nnv=Kv.NbDoF();    assert(mu==mmu && nv == nnv) ;                 const Opera &Op(*mat.bilinearform);    bool classoptm = copt && Op.optiexpK;    //  if (Ku.number<1 && verbosity/100 && verbosity % 10 == 2)     if (Ku.number<1 && ( verbosity > 1 ) )      cout << "Element_OpVF P: copt = " << copt << " " << classoptm << " binside (For FH) =" << binside <<endl;          KN<bool> Dop(last_operatortype); //  sinon ca plate bizarre     Op.DiffOp(Dop);      int lastop=1+Dop.last(binder1st<equal_to<bool> >(equal_to<bool>(),true));    //assert(lastop<=3);    int lffv = nv*N*last_operatortype;      int lffu = mu*M*last_operatortype;    int loffset =  same ? 0 :  (nv+nnv)*N*last_operatortype;        RNMK_ fv(p,nv,N,lastop); //  the value for basic fonction in K    RNMK_ ffv(p + lffv ,nnv,N,lastop); //  the value for basic fonction in KK    RNMK_ fu(  (double*) fv   + loffset  ,mu,M,lastop); //  the value for basic fonction    RNMK_ ffu( (double*) fu  + lffu  ,mmu,M,lastop); //  the value for basic fonction        R2 E=T.Edge(ie);    double le = sqrt((E,E));    R2 PA(TriangleHat[VerticesOfTriangularEdge[ie][0]]),      PB(TriangleHat[VerticesOfTriangularEdge[ie][1]]),      PC(TriangleHat[OppositeVertex[ie]]);    // warning the to edge are in opposite sens             R2 PP_A(TriangleHat[VerticesOfTriangularEdge[iie][1]]),      PP_B(TriangleHat[VerticesOfTriangularEdge[iie][0]]),      PP_C(TriangleHat[OppositeVertex[ie]]);    R2 Normal(E.perp()/-le);     for (npi=0;npi<FIb.n;npi++) // loop on the integration point      {        pa =a;        QuadratureFormular1dPoint pi( FIb[npi]);                double coef = le*pi.a;        double sa=pi.x,sb=1-sa;        R2 Pt(PA*sa+PB*sb ); //        R2 PP_t(PP_A*sa+PP_B*sb ); //          if (binside) {	  Pt   = (1-binside)*Pt + binside*PC; 	  PP_t  = (1-binside)*PP_t + binside*PP_C; }        Ku.BF(Dop,Pt,fu);        KKu.BF(Dop,PP_t,ffu);        if (!same) { Kv.BF(Dop,Pt,fv); KKv.BF(Dop,PP_t,ffv); }             // int label=-999999; // a passer en argument         MeshPointStack(stack)->set(T(Pt),Pt,Kv,label, Normal,ie);        if (classoptm) (*Op.optiexpK)(stack); // call optim version                         for ( i=0;  i<n;   i++ )              {               int ik= mat.nik[i];              int ikk=mat.nikk[i];                              RNM_ wi(fv(Max(ik,0),'.','.'));                 RNM_ wwi(ffv(Max(ikk,0),'.','.'));                                   for ( j=0;  j<m;   j++,pa++ )                 {                   int jk= mat.njk[j];                  int jkk=mat.njkk[j];                                      RNM_ wj(fu(Max(jk,0),'.','.'));                  RNM_ wwj(ffu(Max(jkk,0),'.','.'));                                    int il=0;                  for (BilinearOperator::const_iterator l=Op.v.begin();l!=Op.v.end();l++,il++)                      {                               BilinearOperator::K ll(*l);                        pair<int,int> jj(ll.first.first),ii(ll.first.second);                        int iis = ii.second, jjs=jj.second;                                                int iicase  = iis / last_operatortype;                        int jjcase  = jjs / last_operatortype;                                                 iis %= last_operatortype;                         jjs %= last_operatortype;                        double w_i=0,w_j=0,ww_i=0,ww_j=0;                                                if(ik>=0) w_i =   wi(ii.first,iis );                         if(jk>=0) w_j =   wj(jj.first,jjs );                                                if( iicase>0 && ikk>=0) ww_i =  wwi(ii.first,iis );                         if( jjcase>0 && jkk>=0) ww_j =  wwj(jj.first,jjs );                                                                       if       (iicase==Code_Jump) w_i = ww_i-w_i; // jump                        else  if (iicase==Code_Mean) {                                                         w_i = cmean*  (w_i + ww_i );} // average                        else  if (iicase==Code_OtherSide) w_i = ww_i;  // valeur de autre cote                                                if      (jjcase==Code_Jump) w_j = ww_j-w_j; // jump                        else if (jjcase==Code_Mean) w_j = cmean*  (w_j +ww_j ); // average                        else if (jjcase==Code_OtherSide) w_j = ww_j;  //  valeur de l'autre cote                                                   // R ccc = GetAny<R>(ll.second.eval(stack));                                               R ccc = copt ? *(copt[il]) : GetAny<R>(ll.second.eval(stack));                       if ( copt && Kv.number <1)                        {                         R cc  =  GetAny<R>(ll.second.eval(stack));                         if ( ccc != cc) {                           cerr << cc << " != " << ccc << " => ";                         cerr << "Sorry error in Optimization (b) add:  int2d(Th,optimize=0)(...)" << endl;                         ExecError("In Optimized version "); }                 }                         *pa += coef * ccc * w_i*w_j;                      }                }            }          // else pa += m;      }         pa=a;     if (verbosity > 55 && (Ku.number <=0 || KKu.number <=0 )) {        cout <<endl  << " edge between " << Ku.number << " , " <<  KKu.number   << " =  "<<  T[0] << ", " << T[1] << ", " << T[2] << " " << nx << endl;       cout << " K u, uu =  " << Ku.number << " " << KKu.number << " " <<  " K v, vv =  " << Kv.number << " " << KKv.number << " " <<endl;        for (int i=0;i<n;i++)	 {	   cout << setw(2) << i << setw(4) << mat.ni[i] <<  setw(4) << mat.nik[i] << setw(4) << mat.nikk[i]  <<  " :";	   for (int j=0;j<m;j++)	     cout << setw(5)  << (*pa++) << " ";	   cout << endl;	 } }           *MeshPointStack(stack) = mp;  }   //-------------------------------------------------------------------------------------- // --------- FH 120105 template<class R> void AssembleBilinearForm(Stack stack,const Mesh & Th,const FESpace & Uh,const FESpace & Vh,bool sym,			   MatriceCreuse<R>  & A, const  FormBilinear * b  )    {   StackOfPtr2Free * sptr = WhereStackOfPtr2Free(stack);   bool sptrclean=true;   const CDomainOfIntegration & di= *b->di;   const Mesh * pThdi = GetAny<pmesh>( (* di.Th)(stack));   if ( pThdi != &Th) {      ExecError("No way to compute bilinear form with integrale of on mesh \n"	       "  test  or unkown function  defined on an other mesh! sorry to hard.   ");   }   SHOWVERB(cout << " FormBilinear " << endl);    MatriceElementaireSymetrique<R,FESpace> *mates =0;    MatriceElementairePleine<R,FESpace> *matep =0;    const bool useopt=di.UseOpt(stack);        double binside=di.binside(stack);        const vector<Expression>  & what(di.what);                 CDomainOfIntegration::typeofkind  kind = di.kind;    set<int> setoflab;    bool all=true;     const QuadratureFormular1d & FIE = di.FIE(stack);    const QuadratureFormular & FIT = di.FIT(stack);    bool VF=b->VF();  // finite Volume or discontinous Galerkin    if (verbosity>2) cout << "  -- discontinous Galerkin  =" << VF << " size of Mat =" << A.size()<< " Bytes\n";    if (verbosity>3)       if (CDomainOfIntegration::int1d==kind) cout << "  -- boundary int border ( nQP: "<< FIE.n << ") ,"  ;      else  if (CDomainOfIntegration::intalledges==kind) cout << "  -- boundary int all edges ( nQP: "<< FIE.n << "),"  ;      else  if (CDomainOfIntegration::intallVFedges==kind) cout << "  -- boundary int all VF edges nQP: ("<< FIE.n << ")," ;      else cout << "  --  int    (nQP: "<< FIT.n << " ) in "  ;    for (size_t i=0;i<what.size();i++)      {	long  lab  = GetAny<long>( (*what[i])(stack));	setoflab.insert(lab);	if ( verbosity>3) cout << lab << " ";	all=false;      }    if (verbosity>3) cout <<" Optimized = "<< useopt << ", ";    const E_F0 & optiexp0=*b->b->optiexp0;        int n_where_in_stack_opt=b->b->where_in_stack_opt.size();    R** where_in_stack =0;    if (n_where_in_stack_opt && useopt)      where_in_stack = new R * [n_where_in_stack_opt];    if (where_in_stack)

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?