Example #1
0
void PRECO_ILUT::Factor( PROJECT* project, EQS* eqs, CRSMAT* crsm )
{
  REPORT::rpt.Message( 2, "\n (PRECO_ILUT::Factor)    preconditioning: ILUT\n" );


  ////////////////////////////////////////////////////////////////////////////////////////
  // 1.  initializations and memory allocation

  int*     width = crsm->m_width;
  int**    index = crsm->m_index;
  REALPR** A     = crsm->m_A;

  //int*     Iw    = crsi->m_width;
  //int**    Ii    = crsi->m_index;
  REALPR** ILU   = crsi->m_A;

  int ceq    = crsi->m_ceq;

  int neq    = crsm->m_neq;
  int neq_dn = crsm->m_neq_dn;
  int neq_up = crsm->m_neq_up;

  //for( int e=0; e<neq; e++ )  Iw[e] = 1;

  //crsi->Init();


  // allocate dynamic front memory -------------------------------------------------------

  int mfw = 4 * ceq;

  fromat = new FROMAT( mfw, neq );

  if( !fromat )
    REPORT::rpt.Error( kMemoryFault, "can not allocate memory - PRECO_ILUT::Factor(1)" );


  ////////////////////////////////////////////////////////////////////////////////////////
  // 2.  LU factorization
  //
  // 2.1 MPI: incomplete LU factorization restricted to interior subdomain nodes

# ifdef _MPI_DBG
  REPORT::rpt.Output( " (PRECO_ILUT::Factor)    starting with 2.1\n" );
# endif

  int maximumFW = 0;

  for( int e=0; e<neq_up; e++ )
  {
    if( fabs(A[e][0]) < kMinPivot )
    {
      REPORT::rpt.Error( kParameterFault, "%s - PRECO_ILUT::Factor(2)",
                         "factorization can not be applied to the matrix" );
    }

    // equation "e" is elimination equation ----------------------------------------------

    fromat->Insert( e, width, index, A );

    if( fromat->m_actFW > maximumFW )  maximumFW = fromat->m_actFW;

#   ifdef kEqCounter
    if( ((e+1)%1000) == 0 )
    {
      REPORT::rpt.Screen( 2, "\r (PRECO_ILUT::Factor)    %d (maximum FW = %d)", e+1, maximumFW );
    }
#   endif

    fromat->Eliminate( e );

    ILU[e][0] = (REALPR) fromat->m_U[fromat->m_actFW];      // diagonal element

    //if( fabs(ILU[e][0]) < kZero )
    //{
    //  REPORT::rpt.Error( kParameterFault, "%s - PRECO_ILUT::Factor(2)",
    //                     "factorization can not be applied to the matrix" );
    //}

    for( int i=1; i<width[e]; i++ )
    {
      int f = index[e][i];
      int j = fromat->m_eql[f].ind;

      if( f > e )
      {
        ILU[e][i] = (REALPR) fromat->m_U[j];

        for( int k=1; k<width[f]; k++ )
        {
          if( index[f][k] == e )
          {
            ILU[f][k] = (REALPR) fromat->m_L[j];
            break;
          }
        }
      }
    }

    //fromat->Sort();

    //Ii[e][0]  = e;
    //ILU[e][0] = (REALPR) fromat->m_eqtr[fromat->m_actFW].U;

    //EQTREE* eqtr = (EQTREE*) fromat->m_root.First();

    //while( eqtr )
    //{
    //  int i;
    //  int f = eqtr->e;

    //  i         = Iw[e];
    //  Ii[e][i]  = f;
    //  ILU[e][i] = (REALPR) eqtr->U;
    //  Iw[e]++;

    //  i         = Iw[f];
    //  Ii[f][i]  = e;
    //  ILU[f][i] = (REALPR) eqtr->L;
    //  Iw[f]++;

    //  if( Iw[e] >= ceq  ||  Iw[f] >= ceq/2 ) break;

    //  eqtr = (EQTREE*) eqtr->Next();
    //}


    // ...
  }


  ////////////////////////////////////////////////////////////////////////////////////////
  // 2.2 MPI communication:
  //     receive interface equations from subdomains with smaller pid (2 <- 1)
  //     s < pid  ==> upstream interface nodes

//# ifdef _MPI_DBG
//  REPORT::rpt.Output( " (PRECO_ILUT::Factor)    starting with 2.2\n" );
//# endif

# ifdef _MPI_

  if( project->subdom.npr > 1 )
  {
    SUBDOM* subdom = &project->subdom;
    INFACE* inface = subdom->inface;

    MPI_Status status;

    int df = eqs->dfcn;

    for( int s=subdom->npr-1; s>=0; s-- )
    {
      int np = inface[s].np;                      // number of interface nodes

      if( np > 0  &&  s < subdom->pid )           // upstream interface nodes
      {
        for( int n=0; n<np; n++ )
        {
          NODE* ndr = inface[s].node[n];

          if( !isFS(ndr->flag, NODE::kDry) )      // nothing to do if node is dry...
          {
            SUB* subr = ndr->sub;
            while( subr )
            {
              if( subr->no == s )  break;
              subr = subr->next;
            }

            if( !subr->dry )                       // ...or if the node is dry in
            {                                     // any adjacent subdomain
              for( int e=0; e<df; e++ )
              {
                int req = eqs->GetEqno( ndr, e );

                if( req >= 0 )
                {
                  int cnt;

                  MPI_Recv( &cnt, 1, MPI_INT, s, 1, MPI_COMM_WORLD, &status );

                  if( cnt )
                  {
                    MPI_Recv( inface[s].ria1, cnt, MPI_CHAR,   s, 2, MPI_COMM_WORLD, &status );
                    MPI_Recv( inface[s].ria2, cnt, MPI_INT,    s, 3, MPI_COMM_WORLD, &status );
                    MPI_Recv( inface[s].recv, cnt, MPI_DOUBLE, s, 4, MPI_COMM_WORLD, &status );

                    for( int j=0; j<cnt; j++ )
                    {
                      int   eid  = inface[s].ria1[j];
                      int   name = inface[s].ria2[j];
                      NODE* ndc  = subdom->node[name - 1];

                      if( ndc )
                      {
                        int ceq = eqs->GetEqno( ndc, eid );

                        for( int c=0; c<width[req]; c++ )
                        {
                          if( index[req][c] == ceq )
                          {
                            ILU[req][c] += (REALPR)inface[s].recv[j];
                            break;
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }


  ////////////////////////////////////////////////////////////////////////////////////////
  // 2.3 MPI: factorization of interface nodes

//# ifdef _MPI_DBG
//  REPORT::rpt.Output( " (PRECO_ILUT::Factor)    starting with 2.3\n" );
//# endif

  for( int e=neq_up; e<neq_dn; e++ )
  {
    if( fabs(ILU[e][0]) < kMinPivot )
    {
      int    piv = -1;
      double max = 0.0;

      for( int j=1; j<width[e]; j++ )
      {
        int eq = index[e][j];

        if( eq > e )
        {
          // find column "e" in equation "eq" --------------------------------------------

          for( int k=0; k<width[eq]; k++ )
          {
            if( index[eq][k] == e )
            {
              double p = fabs( ILU[eq][k] );

              if( p > max )
              {
                piv = eq;
                max = p;
              }
            }
          }
        }
      }

      if( piv > 0 )
      {
        for( int j=0; j<width[e]; j++ )
        {
          for( int k=0; k<width[piv]; k++ )
          {
            if( index[e][j] == index[piv][k] )  ILU[e][j] += ILU[piv][k];
          }
        }
      }
      else
      {
        REPORT::rpt.Error( kParameterFault, "ILU-Factorization cannot be applied to the matrix" );
      }
    }


    // equation "e" is elimination equation ----------------------------------------------

    for( int j=1; j<width[e]; j++ )
    {
      int eq = index[e][j];

      if( eq > e )// &&  eq > neq_dn ) // Note: The elimination of just received upstream
      {                                // equations (2.2) was performed in prior subdomain
        double factor = 0.0;

        // find column "e" in equation "eq" and compute elimination factor ---------------

        int k;

        for( k=0; k<width[eq]; k++ )
        {
          if( index[eq][k] == e )
          {
            factor = -ILU[eq][k] / ILU[e][0];
            break;
          }
        }


        // save elimination factor (L-Matrix: index[eq][k] == e < eq) --------------------

        ILU[eq][k] = (REALPR)factor;


        // add elimination equation ILU[i] to ILU[eq] ------------------------------------

        for( k=1; k<width[e]; k++ )
        {
          if( index[e][k] >= e )
          {
            for( int l=0; l<width[eq]; l++ )
            {
              if( index[eq][l] == index[e][k] )
              {
                ILU[eq][l] += (REALPR)factor * ILU[e][k];
                break;
              }
            }
          }
        }
      }
    }
  }


  ////////////////////////////////////////////////////////////////////////////////////////
  // 2.4 MPI communication:
  //     send to subdomain with larger pid      (2 -> 3)
  //     s > pid  ==> downstream interface nodes

//# ifdef _MPI_DBG
//  REPORT::rpt.Output( " (PRECO_ILUT::Factor)    starting with 2.4\n" );
//# endif

  if( project->subdom.npr > 1 )
  {
    SUBDOM* subdom = &project->subdom;
    INFACE* inface = subdom->inface;

    int df = eqs->dfcn;

    for( int s=0; s<subdom->npr; s++ )
    {
      int np = inface[s].np;                      // number of interface nodes

      if( np > 0  &&  s > subdom->pid )           // downstream interface nodes
      {
        for( int n=0; n<np; n++ )
        {
          NODE* ndr = inface[s].node[n];

          if( !isFS(ndr->flag, NODE::kDry) )      // nothing to send if the node is dry...
          {
            SUB* subr = ndr->sub;
            while( subr )
            {
              if( subr->no == s )  break;
              subr = subr->next;
            }

            if( !subr->dry )                      // ...or if the node is dry in
            {                                     // any adjacent subdomain
              for( int e=0; e<df; e++ )
              {
                int req = eqs->GetEqno( ndr, e );

                if( req >= 0 )
                {
                  int cnt = 0;

                  for( int c=0; c<width[req]; c++ )
                  {
                    int   ceq = index[req][c];
                    NODE* ndc = eqs->eqnoNode[ceq];
                    int   eid = eqs->eqid[ceq];

                    // is ndc a point on interface "s"?
                    SUB* subc = ndc->sub;
                    while( subc )
                    {
                      if( subc->no == s )  break;
                      subc = subc->next;
                    }

                    if( subc )
                    {
                      inface[s].sia1[cnt] = eid;
                      inface[s].sia2[cnt] = ndc->Getname();
                      inface[s].send[cnt] = ILU[req][c];
                      cnt++;
                    }
                  }

                  MPI_Send( &cnt, 1, MPI_INT, s, 1, MPI_COMM_WORLD );

                  if( cnt )
                  {
                    MPI_Send( inface[s].sia1, cnt, MPI_CHAR,   s, 2, MPI_COMM_WORLD );
                    MPI_Send( inface[s].sia2, cnt, MPI_INT,    s, 3, MPI_COMM_WORLD );
                    MPI_Send( inface[s].send, cnt, MPI_DOUBLE, s, 4, MPI_COMM_WORLD );
                  }
                }
              }
            }
          }
        }
      }
    }
  }
# endif
  ////////////////////////////////////////////////////////////////////////////////////////

# ifdef kDebug
  {
    char filename[80];

    if( project->subdom.npr == 1 )
      sprintf( filename, "ilu_2.4.dbg" );
    else
      sprintf( filename, "ilu_2.4_%02d.dbg", project->subdom.pid+1 );

    eqs->ExportEQS( filename, crsi, project );
  }

# endif

//# ifdef _MPI_DBG
//  REPORT::rpt.Output( " (PRECO_ILUT::Factor)    ILU factorization finished\n" );
//# endif
}
Example #2
0
void MODEL::DoDryRewet( PROJECT* project, int* dried, int* wetted )
{
  DRYREW *dryRew = &region->dryRew;

  region->Connection( 0L );

  int del = 0;
  int wel = 0;

  if( dryRew->method == 1 )
  {
    // mark nodes and elements to be rewetted ------------------------------------------------------
    wel = region->Rewet( dryRew->rewetLimit, dryRew->rewetPasses, project );

    // mark dry nodes and elements -----------------------------------------------------------------
    del = region->Dry( dryRew->dryLimit, dryRew->countDown );
  }
  else if( dryRew->method == 2 )
  {
    region->DryRewet( dryRew->dryLimit, dryRew->rewetLimit, dryRew->countDown, &del, &wel );
  }
  else if( dryRew->method == 3 )
  {
    region->RewetDry( dryRew->dryLimit, dryRew->rewetLimit, dryRew->countDown, &del, &wel );
  }
/*
  // future work ...
  else if( dryRew->method == 4 )
  {
    // determine dynamic boundary ------------------------------------------------------------------
    region.DynamicBound( np, node, *elem, dryRew->dryLimit, project );
  }
*/

  //////////////////////////////////////////////////////////////////////////////////////////////////

# ifdef _MPI_
  del = project->subdom.Mpi_sum( del );
  wel = project->subdom.Mpi_sum( wel );
# endif

  char text [200];

  sprintf( text, "\n (MODEL::DoDryRewet)     %d elements have got dry\n", del );
  REPORT::rpt.Output( text, 3 );

  sprintf( text, "\n (MODEL::DoDryRewet)     %d elements have got wet\n", wel );
  REPORT::rpt.Output( text, 3 );

  int dryRewFlag = del + wel;

  if( dryRewFlag )
  {
    ////////////////////////////////////////////////////////////////////////////////////////////////
    // exchange information on dry nodes on interfaces
#   ifdef _MPI_
    if( project->subdom.npr > 1 )
    {
      MPI_Comm_Dry( project, true );

      //////////////////////////////////////////////////////////////////////////////////////////////
      // reset wetted area, in case of dry nodes that are not dry in adjacent subdomains
      // added on 20.04.2006, sc

      if( dryRew->method == 2  ||  dryRew->method == 3 )
      {
        int wetted = 0;

        for( int n=0; n<region->Getnp(); n++ )
        {
          NODE* nd = region->Getnode(n);

          nd->mark = false;

          double H = nd->v.S - nd->zor;

          if( H < dryRew->dryLimit )
          {
            SF( nd->flag, NODE::kDry );
          }

          else if( isFS(nd->flag, NODE::kDry) )
          {
            nd->mark = true;

            CF( nd->flag, NODE::kDry );
            wetted++;
          }

          CF( nd->flag, NODE::kMarsh );
          nd->z = nd->zor;
        }


        if( dryRew->method == 2 )
        {
          region->DryRewet( dryRew->dryLimit, dryRew->rewetLimit, dryRew->countDown, &del, &wel );
        }
        else if( dryRew->method == 3 )
        {
          region->RewetDry( dryRew->dryLimit, dryRew->rewetLimit, dryRew->countDown, &del, &wel );
        }

        ////////////////////////////////////////////////////////////////////////////////////////////

        MPI_Comm_Dry( project, false );

        wetted = project->subdom.Mpi_sum( wetted );

        sprintf( text, "\n (MODEL::DoDryRewet)     %d interface nodes have got wet\n", wetted );
        REPORT::rpt.Output( text, 3 );
      }
    }


    ////////////////////////////////////////////////////////////////////////////////////////////////
    // reset interface flags: kInface, kInface_DN and kInface_UP; this is
    // necessary for the correct ordering of equations in EQS::ResetEqOrder()

    project->subdom.SetInface( region );

#   endif  //  #ifdef _MPI_
    ////////////////////////////////////////////////////////////////////////////////////////////////

    // determine 1D boundary elements and ----------------------------------------------------------
    // set up slip velocity boundary conditions

    Initialize();

    SetNormal();
    SetRotation();

    region->SetSlipFlow();

    REPORT::rpt.PrintTime( 3 );

//  ================================================================================================
#   ifdef kDebug_1
    for( int n=0; n<region->Getnp(); n++ )
    {
      NODE* ndbg = region->Getnode(n);

      switch( ndbg->Getname() )
      {
        case 3654:
          REPORT::rpt.Message( "\n" );
          REPORT::rpt.Message( "### NODE %6d: inface    = %d\n", ndbg->Getname(), ndbg->flag&NODE::kInface );
          REPORT::rpt.Message( "###            : inface_dn = %d\n", ndbg->flag&NODE::kInface_DN );
          REPORT::rpt.Message( "###            : inface_up = %d\n", ndbg->flag&NODE::kInface_UP );
          REPORT::rpt.Message( "\n" );
          REPORT::rpt.Message( "###            : dry       = %d\n", ndbg->flag&NODE::kDry );
          REPORT::rpt.Message( "###            : marsh     = %d\n", ndbg->flag&NODE::kMarsh );
          REPORT::rpt.Message( "###            : H         = %f\n", ndbg->v.S - ndbg->zor );
          REPORT::rpt.Message( "\n" );
          REPORT::rpt.Message( "###            : bound     = %d\n", ndbg->flag&NODE::kBound );
          REPORT::rpt.Message( "###            : inflow    = %d\n", ndbg->flag&NODE::kInlet );
          REPORT::rpt.Message( "###            : outflow   = %d\n", ndbg->flag&NODE::kOutlet );
          REPORT::rpt.Message( "###            : rotat     = %d\n", ndbg->flag&NODE::kRotat );
          REPORT::rpt.Message( "###            : noMoment  = %d\n", ndbg->flag&NODE::kNoMoment );
          REPORT::rpt.Message( "\n" );
          REPORT::rpt.Message( "###            : countDown = %d\n", ndbg->countDown );

          {
            SUB* sub = ndbg->sub;
            while( sub )
            {
              REPORT::rpt.Message( "### SUBDOM %4d: dry       = %d\n", sub->no+1, sub->dry );
              sub = sub->next;
            }
          }
          break;
      }
    }
#   endif
//  ================================================================================================
  }

  else
  {
    // set up structure for connection of nodes to elements ----------------------------------------
    // dry elements are not taken into consideration

    region->Connection( ELEM::kDry );
  }

  if( dried )  *dried  = del;
  if( wetted ) *wetted = wel;

  region->firstDryRew = false;
}
Example #3
0
void PRECO_ILUT::Solve( PROJECT* project, EQS* eqs, double* B, double* X )
{
  int      neq    = crsi->m_neq;
  int      neq_dn = crsi->m_neq_dn;
  int      neq_up = crsi->m_neq_up;

  int*     width  = crsi->m_width;
  int**    index  = crsi->m_index;
  REALPR** ILU    = crsi->m_A;


  ////////////////////////////////////////////////////////////////////////////////////////
  // 1.  forward solve: manipulate vector B with lower part of matrix ILU
  //
  // 1.1 MPI: forward solve for interior subdomain nodes

# ifdef _MPI_DBG
  REPORT::rpt.Output( " (PRECO_ILUT::Solve)     starting with 1.1\n" );
# endif

  for( int i=0; i<neq_up; i++ )
  {
    X[i] = B[i];

    for( int j=1; j<width[i]; j++ )
    {
      int eq = index[i][j];

      if( eq < i )  // L-matrix
      {
        X[i] += ILU[i][j] * X[eq];
      }
    }
  }


  ////////////////////////////////////////////////////////////////////////////////////////
  // 1.2 MPI communication:
  //     receive from subdomains with smaller pid  (2 <- 1)
  //     s < pid  ==> upstream interface nodes

# ifdef _MPI_DBG
  REPORT::rpt.Output( " (PRECO_ILUT::Solve)     starting with 1.2\n" );
# endif

# ifdef _MPI_

  if( project->subdom.npr > 1 )
  {
    SUBDOM* subdom = &project->subdom;
    INFACE* inface = subdom->inface;

    MPI_Status status;

    int df = eqs->dfcn;

    for( int s=subdom->npr-1; s>=0; s-- )
    {
      int np = inface[s].np;                      // number of interface nodes

      if( np > 0  &&  s < subdom->pid )           // upstream interface nodes
      {
        int cnt = 0;

#       ifdef _MPI_DBG
        {
          char text[200];
          sprintf( text, " ### receiving from %d:", s+1 );
          REPORT::rpt.Output( text );
        }
#       endif

        MPI_Recv( &cnt, 1, MPI_INT, s, 1, MPI_COMM_WORLD, &status );

#       ifdef _MPI_DBG
        {
          char text[200];
          sprintf( text, " %d values\n", cnt );
          REPORT::rpt.Output( text );
        }
#       endif

        if( cnt )
        {
          MPI_Recv( inface[s].recv, cnt, MPI_DOUBLE, s, 2, MPI_COMM_WORLD, &status );

          cnt = 0;

          for( int n=0; n<np; n++ )
          {
            NODE* nd = inface[s].node[n];

            if( !isFS(nd->flag, NODE::kDry) )       // nothing received if node is dry...
            {
              SUB* sub = nd->sub;
              while( sub )
              {
                if( sub->no == s )  break;
                sub = sub->next;
              }

              if( !sub->dry )                       // ...or if the node is dry in
              {                                     // any adjacent subdomain
                for( int e=0; e<df; e++ )
                {
                  int eqno = eqs->GetEqno( nd, e );

                  if( eqno >= 0 )
                  {
                    X[eqno] = inface[s].recv[cnt];
                    cnt++;
                  }
                }
              }
            }
          }
        }
      }
    }
  }


  ////////////////////////////////////////////////////////////////////////////////////////
  // 1.3 MPI: forward solve for upstream interface nodes
  //          Note: X[i] is not initialized with B[i] since
  //                this was performed in prior subdomain

# ifdef _MPI_DBG
  REPORT::rpt.Output( " (PRECO_ILUT::Solve)     starting with 1.3\n" );
# endif

  for( int i=neq_up; i<neq_dn; i++ )
  {
    for( int j=1; j<width[i]; j++ )
    {
      int eq = index[i][j];

      if( eq < i )
      {
        X[i] += ILU[i][j] * X[eq];
      }
    }
  }


  ////////////////////////////////////////////////////////////////////////////////////////
  // 1.4 MPI: faktorisation of downstream interface nodes

# ifdef _MPI_DBG
  REPORT::rpt.Output( " (PRECO_ILUT::Solve)     starting with 1.4\n" );
# endif

  for( int i=neq_dn; i<neq; i++ )
  {
    X[i] = B[i];

    for( int j=1; j<width[i]; j++ )
    {
      int eq = index[i][j];

      if( eq < neq_dn )
      {
        X[i] += ILU[i][j] * X[eq];
      }
    }
  }


  ////////////////////////////////////////////////////////////////////////////////////////
  // 1.5 MPI communication:
  //     send to subdomains with larger pid        (2 -> 3)
  //     s > pid  ==> downstream interface nodes

# ifdef _MPI_DBG
  REPORT::rpt.Output( " (PRECO_ILUT::Solve)     starting with 1.5\n" );
# endif

  if( project->subdom.npr > 1 )
  {
    SUBDOM* subdom = &project->subdom;
    INFACE* inface = subdom->inface;

    int df = eqs->dfcn;

    for( int s=0; s<subdom->npr; s++ )
    {
      int np = inface[s].np;                      // number of interface nodes

      if( np > 0  &&  s > subdom->pid )           // downstream interface nodes
      {
        int cnt = 0;

        for( int n=0; n<np; n++ )
        {
          NODE* nd = inface[s].node[n];

          if( !isFS(nd->flag, NODE::kDry) )       // nothing to send if the node is dry...
          {
            SUB* sub = nd->sub;
            while( sub )
            {
              if( sub->no == s )  break;
              sub = sub->next;
            }

            if( !sub->dry )                       // ...or if the node is dry in
            {                                     // any adjacent subdomain
              for( int e=0; e<df; e++ )
              {
                int eqno = eqs->GetEqno( nd, e );

                if( eqno >= 0 )
                {
                  inface[s].send[cnt] = X[eqno];
                  cnt++;
                }
              }
            }
          }
        }

#       ifdef _MPI_DBG
        {
          char text[200];
          sprintf( text, " ### sending %d values to %d\n", cnt, s+1 );
          REPORT::rpt.Output( text );
        }
#       endif

        MPI_Send( &cnt, 1, MPI_INT, s, 1, MPI_COMM_WORLD );
        if( cnt ) MPI_Send( inface[s].send, cnt, MPI_DOUBLE, s, 2, MPI_COMM_WORLD );
      }
    }
  }

# endif
  ////////////////////////////////////////////////////////////////////////////////////////

# ifdef kDebug
  {
    FILE* dbg;
    char  filename[80];

    MODEL* model  = project->M2D;
    GRID*  region = model->region;

    if( project->subdom.npr == 1 )
      sprintf( filename, "forwX.dbg" );
    else
      sprintf( filename, "forwX_%02d.dbg", project->subdom.pid );

    dbg = fopen( filename, "w" );
    fprintf( dbg, "%d\n", region->Getnp() );

    for( int n=0; n<region->Getnp(); n++ )
    {
      NODE* nd = region->Getnode( n );
      for( int e=0; e<eqs->dfcn; e++ )
      {
        int eqno = eqs->GetEqno( nd, e );
        fprintf( dbg, "%5d %1d ", nd->Getname(), e );
        if( eqno >= 0 )
          fprintf( dbg, "%14.6le\n", X[eqno] );
        else
          fprintf( dbg, "%14.6le\n", 0.0 );
      }
    }

    fclose( dbg );
  }
# endif

# ifdef _MPI_DBG
  REPORT::rpt.Output( " (PRECO_ILUT::Solve)     forward solve finished\n" );
# endif

  ////////////////////////////////////////////////////////////////////////////////////////
  // 2.  solve for X with upper part of matrix ILU (backward substitution)
  //
  // 2.1 MPI communication:
  //     receive from subdomains with larger pid    (2 <- 3)
  //     s > pid  ==> downstream interface nodes

# ifdef _MPI_DBG
  REPORT::rpt.Output( " (PRECO_ILUT::Solve)     starting with 2.1\n" );
# endif

# ifdef _MPI_

  if( project->subdom.npr > 1 )
  {
    SUBDOM* subdom = &project->subdom;
    INFACE* inface = subdom->inface;

    MPI_Status status;

    int df = eqs->dfcn;

    for( int s=subdom->npr-1; s>=0; s-- )
    {
      int np = inface[s].np;                // number of interface nodes

      if( np > 0  &&  s > subdom->pid )     // downstream interface nodes
      {
        int cnt = 0;

#       ifdef _MPI_DBG
        {
          char text[200];
          sprintf( text, " ### receiving from %d:", s+1 );
          REPORT::rpt.Output( text );
        }
#       endif

        MPI_Recv( &cnt, 1, MPI_INT, s, 1, MPI_COMM_WORLD, &status );

#       ifdef _MPI_DBG
        {
          char text[200];
          sprintf( text, " %d values\n", cnt );
          REPORT::rpt.Output( text );
        }
#       endif

        if( cnt )
        {
          MPI_Recv( inface[s].recv, cnt, MPI_DOUBLE, s, 2, MPI_COMM_WORLD, &status );

          cnt = 0;

          for( int n=0; n<np; n++ )
          {
            NODE* nd = inface[s].node[n];

            if( !isFS(nd->flag, NODE::kDry) )       // nothing received if node is dry...
            {
              SUB* sub = nd->sub;
              while( sub )
              {
                if( sub->no == s )  break;
                sub = sub->next;
              }

              if( !sub->dry )                       // ...or if the node is dry in
              {                                     // any adjacent subdomain
                for( int e=0; e<df; e++ )
                {
                  int req = eqs->GetEqno( nd, e );

                  if( req >= 0 )
                  {
                    X[req] = inface[s].recv[cnt];
                    cnt++;
                  }
                }
              }
            }
          }
        }
      }
    }
  }


  ////////////////////////////////////////////////////////////////////////////////////////
  // 2.2 MPI: solve for upstream interface nodes

# ifdef _MPI_DBG
  REPORT::rpt.Output( " (PRECO_ILUT::Solve)     starting with 2.2\n" );
# endif

  for( int i=neq_dn-1; i>=neq_up; i-- )
  {
    for( int j=1; j<width[i]; j++ )
    {
      int eq = index[i][j];

      if( eq > i )
      {
        X[i] -= ILU[i][j] * X[eq];
      }
    }

    if( fabs(ILU[i][0]) < kZero )
      REPORT::rpt.Error( kParameterFault, "division by zero - EQS::ILU_solver(1)" );

    X[i] /= ILU[i][0];
  }


  ////////////////////////////////////////////////////////////////////////////////////////
  // 2.3 MPI communication:
  //     send to subdomains with smaller pid        (2 -> 1)
  //     s < pid  ==> upstream interface nodes

# ifdef _MPI_DBG
  REPORT::rpt.Output( " (PRECO_ILUT::Solve)     starting with 2.3\n" );
# endif

  if( project->subdom.npr > 1 )
  {
    SUBDOM* subdom = &project->subdom;
    INFACE* inface = subdom->inface;

    int df = eqs->dfcn;

    for( int s=0; s<subdom->npr; s++ )
    {
      int np = inface[s].np;                      // number of interface nodes

      if( np > 0  &&  s < subdom->pid )           // upstream interface nodes
      {
        int cnt = 0;

        for( int n=0; n<np; n++ )
        {
          NODE* nd = inface[s].node[n];

          if( !isFS(nd->flag, NODE::kDry) )       // nothing to send if node is dry...
          {
            SUB* sub = nd->sub;
            while( sub )
            {
              if( sub->no == s )  break;
              sub = sub->next;
            }

            if( !sub->dry )                       // ...or if the node is dry in
            {                                     // any adjacent subdomain
              for( int e=0; e<df; e++ )
              {
                int eqno = eqs->GetEqno( nd, e );

                if( eqno >= 0 )
                {
                  inface[s].send[cnt] = X[eqno];
                  cnt++;
                }
              }
            }
          }
        }

#       ifdef _MPI_DBG
        {
          char text[200];
          sprintf( text, " ### sending %d values to %d\n", cnt, s+1 );
          REPORT::rpt.Output( text );
        }
#       endif

        MPI_Send( &cnt, 1, MPI_INT, s, 1, MPI_COMM_WORLD );
        if( cnt )  MPI_Send( inface[s].send, cnt, MPI_DOUBLE, s, 2, MPI_COMM_WORLD );
      }
    }
  }

# endif
  ////////////////////////////////////////////////////////////////////////////////////////

  ////////////////////////////////////////////////////////////////////////////////////////
  // 2.4 MPI: backward solve for interior nodes

# ifdef _MPI_DBG
  REPORT::rpt.Output( " (PRECO_ILUT::Solve)     starting with 2.4\n" );
# endif

  for( int i=neq_up-1; i>=0; i-- )
  {
    for( int j=1; j<width[i]; j++ )
    {
      int eq = index[i][j];

      if( eq > i )
      {
        X[i] -= ILU[i][j] * X[eq];
      }
    }

    if( fabs(ILU[i][0]) < kZero )
      REPORT::rpt.Error( kParameterFault, "division by zero - EQS::ILU_solver(2)" );

    X[i] /= ILU[i][0];
  }

# ifdef kDebug
  {
    FILE* dbg;
    char  filename[80];

    MODEL* model  = project->M2D;
    GRID*  region = model->region;

    if( project->subdom.npr == 1 )
      sprintf( filename, "backX.dbg" );
    else
      sprintf( filename, "backX_%02d.dbg", project->subdom.pid );

    dbg = fopen( filename, "w" );
    fprintf( dbg, "%d\n", region->Getnp() );

    for( int n=0; n<region->Getnp(); n++ )
    {
      NODE* nd = region->Getnode( n );
      for( int e=0; e<eqs->dfcn; e++ )
      {
        fprintf( dbg, "%5d %1d ", nd->Getname(), e );

        int eqno = eqs->GetEqno( nd, e );

        if( eqno >= 0 )
          fprintf( dbg, "%14.6le\n", X[eqno] );
        else
          fprintf( dbg, "%14.6le\n", 0.0 );
      }
    }

    fclose( dbg );
  }

  MPI_Barrier( MPI_COMM_WORLD );

# endif

# ifdef _MPI_DBG
  REPORT::rpt.Output( " (PRECO_ILUT::Solve)     backward solve finished\n" );
# endif
}
Example #4
0
void CRSMAT::AssembleEqs_im( EQS*     eqs,
                             double*  vector,
                             MODEL*   model,
                             PROJECT* project )
{
  int neq  = eqs->neq;
  int dfcn = eqs->dfcn;
  int dfel = eqs->dfel;

  double*  force  = eqs->force;
  double** estifm = eqs->estifm;

  REPORT::rpt.Message( 3, "\n (CRSMAT::Assemble...)   %s (%d elements)\n",
                          "assembling eqs", model->ne );


  // initializations ---------------------------------------------------------------------

  for( int i=0; i<neq; i++ )  vector[i] = 0.0;


  // -------------------------------------------------------------------------------------
  // assemble elements

  for( int e=0; e<model->ne; e++ )
  {
    ELEM* el = model->elem[e];


    // compute element coefficients ------------------------------------------------------

    if( !eqs->Coefs(el, project, estifm, force) )  continue;

    int nnd = el->Getnnd();


    // insert element stiffness matrix (estifm) and (force) ------------------------------

    for( int i=0; i<nnd; i++ )               // loop on nodes
    {
      for( int j=0; j<dfcn; j++ )            // loop on node-equations
      {
        int rind = i + j*nnd;
        int row  = eqs->GetEqno( el->nd[i], j );

        if( row >= 0 )
        {
          REALPR* APtr      = m_A[row];
          double* estifmPtr = estifm[rind];

          vector[row] += force[rind];

          for( int k=0; k<nnd; k++ )         // loop on nodes
          {
            for( int l=0; l<dfcn; l++ )      // loop on node-equations
            {
              int cind = k + l*nnd;
              int col  = eqs->GetEqno( el->nd[k], l );

              if( col >= 0 )
              {
                for( int m=0; m<m_width[row]; m++ )
                {
                  if( col == m_index[row][m] )
                  {
                    APtr[m] += (REALPR) estifmPtr[cind];
                    break;
                  }
                }
              }
            }
          }

          for( int l=0; l<dfel; l++ )        // loop on element-equations
          {
            int cind = dfcn*nnd + l;
            int col  = eqs->GetEqno( el, l );

            if( col >= 0 )
            {
              for( int m=0; m<m_width[row]; m++ )
              {
                if( col == m_index[row][m] )
                {
                  APtr[m] += (REALPR) estifmPtr[cind];
                  break;
                }
              }
            }
          }
        }
      }
    }


    for( int j=0; j<dfel; j++ )              // loop on element-equations
    {
      int rind = dfcn*nnd + j;
      int row  = eqs->GetEqno( el, j );

      if( row >= 0 )
      {
        REALPR* APtr      = m_A[row];
        double* estifmPtr = estifm[rind];

        vector[row] += force[rind];

        for( int k=0; k<nnd; k++ )           // loop on nodes
        {
          for( int l=0; l<dfcn; l++ )        // loop on node-equations
          {
            int cind = k + l*nnd;
            int col  = eqs->GetEqno( el->nd[k], l );

            if( col >= 0 )
            {
              for( int m=0; m<m_width[row]; m++ )
              {
                if( col == m_index[row][m] )
                {
                  APtr[m] += (REALPR) estifmPtr[cind];
                  break;
                }
              }
            }
          }
        }


        for( int l=0; l<dfel; l++ )          // loop on element-equations
        {
          int cind = dfcn*nnd + l;
          int col  = eqs->GetEqno( el, l );

          if( col >= 0 )
          {
            for( int m=0; m<m_width[row]; m++ )
            {
              if( col == m_index[row][m] )
              {
                APtr[m] += (REALPR) estifmPtr[cind];
                break;
              }
            }
          }
        }
      }
    }
  }


  REPORT::rpt.Message( 3, "\n\n%-25s%s\n\n%15s %1s  %8s  %14s  %14s\n\n",
                          " (CRSMAT::Assemble...)", "Newton-Raphson-residuum / force vector ...",
                          " ", " ", "  node", "   average", "   maximum" );

  for( int e=0; e<dfcn; e++ )
  {
    int    no  = 0;
    double ave = 0.0;
    double max = 0.0;

    for( int n=0; n<model->np; n++ )
    {
      NODE* nd = model->node[n];
      int eqno = eqs->GetEqno( nd, e );

      if( eqno >= 0 )
      {
        double vec = vector[eqno];

        ave += vec;
        if( fabs(vec) > fabs(max) )
        {
          max = vec;
          no  = nd->Getname();
        }
      }
    }

    int tot = neq;

    //////////////////////////////////////////////////////////////////////////////////////
#   ifdef _MPI_
    max = project->subdom.Mpi_max( max );
    tot = project->subdom.Mpi_sum( eqs->neq_up );
    ave = project->subdom.Mpi_sum( ave );
#   endif
    //////////////////////////////////////////////////////////////////////////////////////

    if( tot )  ave /= tot;

    REPORT::rpt.Message( 3, " %15s %1d  %8d  %14.5le  %14.5le\n", " ", e+1, no, ave, max );
  }

  REPORT::rpt.Message( 3, "\n" );
}
Example #5
0
void MODEL::MPI_Comm_Dry( PROJECT* project, int initialize )
{
# ifdef _MPI_

  DRYREW* dryRew = &region->dryRew;

  SUBDOM* subdom = &project->subdom;
  INFACE* inface = subdom->inface;


  // loop on all interfaces: exchange dry flag -----------------------------------------------------
  // set sub->dry flag for dry interface nodes in adjacent subdomains

  for( int s=0; s<subdom->npr; s++ )
  {
    MPI_Status status;

    int np = inface[s].np;

    if( np > 0 )
    {
      // initialize the flag "nd->sub->dry" --------------------------------------------------------

      for( int n=0; n<np; n++ )
      {
        NODE* nd = inface[s].node[n];

        SUB* sub = nd->sub;
        while( sub )
        {
          if( sub->no == s )  sub->dry = false;
          sub = sub->next;
        }

        if( isFS(nd->flag, NODE::kDry) )  inface[s].sia1[n] = true;
        else                              inface[s].sia1[n] = false;
      }


      // exchange data on interface nodes ----------------------------------------------------------

      MPI_Sendrecv( inface[s].sia1, np, MPI_CHAR, s, 1,
                    inface[s].ria1, np, MPI_CHAR, s, 1,
                    MPI_COMM_WORLD, &status );


      // set the flag "nd->sub->dry" for dry nodes in adjacent subdomain and -----------------------
      // adjust water elevation (necessary for just wetted interface nodes)

      for( int n=0; n<np; n++ )
      {
        NODE* nd = inface[s].node[n];

        if( inface[s].ria1[n] )
        {
          SUB* sub = nd->sub;
          while( sub )
          {
            if( sub->no == s )  sub->dry = true;
            sub = sub->next;
          }
        }
      }
    }
  }


  // average data across domains (necessary for wetting interfaces) --------------------------------

  if( initialize )
  {
    MPI_Status status;

    int  rgnp = region->Getnp();
    int* cnt  = (int*) MEMORY::memo.Array_nd( rgnp );

    for( int n=0; n<rgnp; n++ )  cnt[n] = 1;

    for( int s=0; s<subdom->npr; s++ )
    {
      int npinf = inface[s].np;

      if( npinf > 0 )
      {
        for( int n=0; n<npinf; n++ )
        {
          NODE* nd = inface[s].node[n];

          inface[s].send[3*n]   = nd->v.U;
          inface[s].send[3*n+1] = nd->v.V;
          inface[s].send[3*n+2] = nd->v.S;
        }
      }
    }

    for( int s=0; s<subdom->npr; s++ )
    {
      int npinf = inface[s].np;

      if( npinf > 0 )
      {
        MPI_Sendrecv( inface[s].send, 3*npinf, MPI_DOUBLE, s, 1,
                      inface[s].recv, 3*npinf, MPI_DOUBLE, s, 1,
                      MPI_COMM_WORLD, &status );

        for( int n=0; n<npinf; n++ )
        {
          NODE* nd = inface[s].node[n];
          SUB* sub = nd->sub;

          while( sub )
          {
            if( sub->no == s )
            {
              if( !sub->dry )
              {
                nd->v.U += inface[s].recv[3*n];
                nd->v.V += inface[s].recv[3*n+1];
                nd->v.S += inface[s].recv[3*n+2];
                cnt[nd->Getno()]++;
              }
            }
            sub = sub->next;
          }
        }
      }
    }

    for( int n=0; n<rgnp; n++ )
    {
      if( cnt[n] > 1 )
      {
        NODE* nd = region->Getnode(n);

        nd->v.U /= cnt[n];
        nd->v.V /= cnt[n];
        nd->v.S /= cnt[n];
      }
    }

    MEMORY::memo.Detach( cnt );
  }

# ifdef kDebug_2
  {
    char text[200];

    sprintf( text, "### DEBUGGING: List of dry interface nodes...\n\n" );
    REPORT::rpt.Output( text, 1 );

    for( int s=0; s<subdom->npr; s++ )
    {
      int np = inface[s].np;

      if( np > 0 )
      {
        sprintf( text, "interface to domain %d\n", s+1 );
        REPORT::rpt.Output( text, 1 );

        for( int n=0; n<np; n++ )
        {
          NODE* nd = inface[s].node[n];

          SUB* sub = nd->sub;
          while( sub )
          {
            if( sub->no == s )
            {
              if( sub->dry )
              {
                if( isFS(nd->flag, NODE::kDry) )
                {
                  sprintf( text, "dry interface node %5d: dry\n", nd->Getname() );
                  REPORT::rpt.Output( text, 1 );
                }
                else
                {
                  sprintf( text, "wet interface node %5d: dry\n", nd->Getname() );
                  REPORT::rpt.Output( text, 1 );
                }
              }
              else
              {
                if( isFS(nd->flag, NODE::kDry) )
                {
                  sprintf( text, "dry interface node %5d: wet\n", nd->Getname() );
                  REPORT::rpt.Output( text, 1 );
                }
                else
                {
                  sprintf( text, "wet interface node %5d: wet\n", nd->Getname() );
                  REPORT::rpt.Output( text, 1 );
                }
              }
            }

            sub = sub->next;
          }
        }
      }
    }
  }
# endif  // #ifdef kDebug_2
# endif  // #ifdef _MPI_
}
Example #6
0
void GRID::ReportDry( PROJECT* project,
                      double   dryLimit,
                      int      countDown )
{
  int dryNodes = false;


  // check for dry nodes -------------------------------------------------------------------

  for( int n=0; n<Getnp(); n++ )
  {
    NODE* nd = Getnode(n);

    nd->countDown = 0;

    CF( nd->flag, NODE::kDry );

    if( (nd->v.S - nd->z) < dryLimit )
    {
      SF( nd->flag, NODE::kDry );

      dryNodes = true;
    }
  }


  // report all dry nodes ------------------------------------------------------------------

  if( dryNodes )
  {
    REPORT::rpt.Output( "\n\n----------------------------------------", 5 );
    REPORT::rpt.Output( "------------------------------\n", 5 );
    REPORT::rpt.Output( "\n ... the following nodes are dry\n", 5 );

    int jdry = 0;

    for( int n=0; n<Getnp(); n++ )
    {
      NODE* nd = Getnode(n);

      if( isFS(nd->flag, NODE::kDry) )
      {
        char text[20];
        sprintf( text, "  %5d", nd->Getname() );
        REPORT::rpt.Output( text, 5 );

        jdry++;
        if( !( jdry % 10) ) REPORT::rpt.Output( "\n", 5 );
      }
    }

    if( jdry % 10 ) REPORT::rpt.Output( "\n", 5 );


    // loop on all elements ----------------------------------------------------------------

    for( int e=0; e<Getne(); e++ )
    {
      ELEM* el = Getelem(e);

      CF( el->flag, ELEM::kDry );

      int nnd = el->Getnnd();

      for( int i=0; i<nnd; i++ )
      {
        if( isFS(el->nd[i]->flag, NODE::kDry) )
        {
          SF( el->flag, ELEM::kDry );
          break;
        }
      }
    }


    for( int n=0; n<Getnp(); n++ )
    {
      NODE* nd = Getnode(n);

      SF( nd->flag, NODE::kDry );
    }


    // loop on all elements: all nodes at wet elements are wet -----------------------------

    for( int e=0; e<Getne(); e++ )
    {
      ELEM* el = Getelem(e);

      if( !isFS(el->flag, ELEM::kDry) )
      {
        int nnd = el->Getnnd();

        for( int i=0; i<nnd; i++ ) CF( el->nd[i]->flag, NODE::kDry );
      }
    }


    int idry = 0;

    REPORT::rpt.Output( "\n ... the following elements are dry\n", 5 );

    for( int e=0; e<Getne(); e++ )
    {
      ELEM* el = Getelem(e);

      if( isFS(el->flag, ELEM::kDry) )
      {
        char text[20];
        sprintf( text, "  %5d", el->Getname() );
        REPORT::rpt.Output( text, 5 );

        idry++;
        if( !( idry % 10) )  REPORT::rpt.Output( "\n", 5 );
      }
    }

    if( idry % 10 )  REPORT::rpt.Output( "\n", 5 );

    REPORT::rpt.Output( "\n", 5 );


    for( int n=0; n<Getnp(); n++ )
    {
      NODE* nd = Getnode(n);

      if( isFS(nd->flag, NODE::kDry) )
      {
        nd->v.U = 0.0;
        nd->v.V = 0.0;
        nd->v.S = nd->z;

        nd->v.K = 0.0;
        nd->v.D = 0.0;

        nd->v.dUdt = 0.0;
        nd->v.dVdt = 0.0;

        nd->v.dSdt = 0.0;
      }
    }
  }
}
Example #7
0
int GRID::Dry( double  dryLimit,
               int     countDown )
{
  // initialization: mark all dry nodes and elements -------------------------------------

  for( int n=0; n<Getnp(); n++ )
  {
    NODE* nd = Getnode(n);

    if( isFS(nd->flag, NODE::kDry) )  nd->mark = true;
    else                              nd->mark = false;

    SF( nd->flag, NODE::kDry );
  }


  for( int e=0; e<Getne(); e++ )
  {
    ELEM* el = Getelem(e);

    if ( isFS(el->flag, ELEM::kDry) )  el->mark = true;
    else                               el->mark = false;

    CF( el->flag, ELEM::kDry );
  }


  // loop on all elements ----------------------------------------------------------------

  for( int e=0; e<Getne(); e++ )
  {
    ELEM* el = Getelem(e);

    int ncn = el->Getncn();

    for( int i=0; i<ncn; i++ )
    {
      // set element dry, if flow depth is less than dry limit ---------------------------
      // or the node was already dry

      double H = el->nd[i]->v.S - el->nd[i]->z;

      if( H < dryLimit  ||  el->nd[i]->mark )
      {
        SF( el->flag, ELEM::kDry );
      }
    }
  }


  // loop on all elements: all nodes at wet elements are wet -----------------------------

  for( int e=0; e<Getne(); e++ )
  {
    ELEM* el = Getelem(e);

    if( !isFS(el->flag, ELEM::kDry) )
    {
      int nnd = el->Getnnd();

      for( int i=0; i<nnd; i++ )  CF( el->nd[i]->flag, NODE::kDry );
    }
  }


  // report all nodes that have got newly dry --------------------------------------------

  REPORT::rpt.Output( "\n (dry)           the following nodes have got dry\n", 5 );

  int jdry = 0;

  for( int n=0; n<Getnp(); n++ )
  {
    NODE* nd = Getnode(n);

    if( isFS(nd->flag, NODE::kDry) )
    {
      nd->v.U = 0.0;
      nd->v.V = 0.0;
      nd->v.S = nd->z;

      nd->v.K = 0.0;
      nd->v.D = 0.0;

      nd->v.dUdt = 0.0;
      nd->v.dVdt = 0.0;

      nd->v.dSdt = 0.0;

      if( !nd->mark )
      {
        nd->countDown = countDown;

        char text[20];
        sprintf( text, "  %5d", nd->Getname() );
        REPORT::rpt.Output( text, 2 );

        jdry++;
        if( !( jdry % 10) )  REPORT::rpt.Output( "\n", 5 );
      }
    }

    nd->mark = false;
  }

  if( jdry % 10 )  REPORT::rpt.Output( "\n", 5 );


  // report all elements that have got newly dry -------------------------------------------

  REPORT::rpt.Output( "\n (dry)           the following elements have got dry\n", 5 );

  int idry = 0;

  for( int e=0; e<Getne(); e++ )
  {
    ELEM* el = Getelem( e );

    if( isFS(el->flag, ELEM::kDry) && !el->mark )
    {
      char text[20];
      sprintf( text, "  %5d", el->Getname() );
      REPORT::rpt.Output( text, 5 );

      idry++;
      if( !( idry % 10) )  REPORT::rpt.Output( "\n", 5 );
    }

    el->mark = false;
  }

  if( idry % 10 )  REPORT::rpt.Output( "\n", 5 );


  return idry + jdry;
}
Example #8
0
int GRID::Rewet( double   rewetLimit,
                 int      rewetPasses,
                 PROJECT* project )
{
  int i, j, k;
  int l, m, pass, ncn, nnd, rewetFlag;
  double wElev, K, D, cm, cd, vt;
  char text[80];

  cm = project->KD.cm;
  cd = project->KD.cd;


  // initialization: mark all dry elements -----------------------------------------------

  for( int e=0; e<Getne(); e++ )
  {
    ELEM* el = Getelem(e);

    el->mark = false;

    if( isFS(el->flag, ELEM::kDry) )
    {
      el->mark = true;
    }
  }


  REPORT::rpt.Output( "\n (rewet)         the following nodes have been rewetted\n", 5 );

  m = 0;

  for( pass=0; pass<rewetPasses; pass++ )
  {
    for( int n=0; n<Getnp(); n++ )
    {
      NODE* nd = Getnode(n);

      nd->mark = false;
    }

    sprintf( text, " pass %d ...\n", pass+1 );
    REPORT::rpt.Output( text, 5 );


    for( int e=0; e<Getne(); e++ )
    {
      ELEM * el = Getelem(e);

      if( isFS(el->flag, ELEM::kBound) )  continue;


      TYPE* type = TYPE::Getid( el->type );


      // look only for dry elements ------------------------------------------------------

      if( isFS(el->flag, ELEM::kDry) )
      {
        // loop on corner nodes: minimal water elevation ---------------------------------

        ncn = el->Getncn();        // number of corner nodes
        nnd = el->Getnnd();        // total number of nodes

        rewetFlag = false;

        wElev = 0.0;

        for( j=0, i=0; j<ncn; j++ )
        {
          if( !isFS(el->nd[j]->flag, NODE::kDry) )
          {
            // determine averaged water elevation at wet points --------------------------

            rewetFlag = true;

            wElev += el->nd[j]->v.S;
            i++;
          }
        }


        // loop on all nodes: check for rewetting ----------------------------------------

        if( i )
        {
          wElev /= i;

          for( j=0; j<nnd; j++ )
          {
            if( (wElev - el->nd[j]->z) < rewetLimit )  rewetFlag = false;
          }
        }


        // if all nodes have been rewetted, rewet whole element --------------------------

        if( rewetFlag )
        {
          for( j=0; j<ncn; j++ )
          {
            // re-initialize flow parameters ---------------------------------------------

            if( isFS(el->nd[j]->flag, NODE::kDry) )
            {
              el->nd[j]->mark = true;
              el->nd[j]->v.S = wElev;
            }
          }

          for( j=ncn; j<nnd; j++ )
          {
            if( isFS(el->nd[j]->flag, NODE::kDry) )
            {
              el->nd[j]->mark = true;

              // get left and right corner node to midside node j ------------------------
              el->GetLShape()->getCornerNodes( j, &i, &k );

              el->nd[j]->v.S = (el->nd[i]->v.S + el->nd[k]->v.S) / 2.0;
            }
          }

          for( j=0; j<nnd; j++ )
          {
            if( isFS(el->nd[j]->flag, NODE::kDry) )
            {
              el->nd[j]->v.U = 0.0;
              el->nd[j]->v.V = 0.0;

              el->nd[j]->v.dUdt = 0.0;
              el->nd[j]->v.dVdt = 0.0;

              el->nd[j]->v.dSdt = 0.0;


              K = el->nd[j]->v.K = dryRew.interpolate(el->nd[j], kVarK, 1);
              D = el->nd[j]->v.D = dryRew.interpolate(el->nd[j], kVarD, 1);

              if( isFS(project->actualTurb, BCONSET::kVtConstant) )
              {
                el->nd[j]->vt = type->vt;
              }
              else if( isFS(project->actualTurb, BCONSET::kVtPrandtlKol) )
              {
                if( fabs(D) > 0.0 )  vt = cm * cd * K * K / D;
                else                 vt = 0.0;

                el->nd[j]->vt = vt;
              }
            }
          }
        }
      }
    }


    // check count down for nodes to be rewetted and report ------------------------------

    l = 0;
    for( int n=0; n<Getnp(); n++ )
    {
      NODE* nd = Getnode(n);

      if( nd->mark )
      {
        nd->countDown--;

        if( nd->countDown <= 0 )
        {
          CF( nd->flag, NODE::kDry );


          // look for boundary conditions ------------------------------------------------

          BCON *bc = &nd->bc;


          // ... outflow boundary or fixed flow depth h --------------------------------

          if( isFS(bc->kind, BCON::kOutlet)  ||  isFS(bc->kind, BCON::kSetS) )
          {
            nd->v.S = bc->val->S;
          }


          // ... inflow boundary or fixed velocities U,V -------------------------------

          if( isFS(bc->kind, BCON::kInlet) )
          {
            nd->v.U = bc->val->U * bc->niox / (nd->v.S - nd->z);
            nd->v.V = bc->val->U * bc->nioy / (nd->v.S - nd->z);
          }

          else if( !isFS(bc->kind, BCON::kAutoSlip) )
          {
            if ( isFS(bc->kind, BCON::kFixU) )  nd->v.U = bc->val->U;
            if ( isFS(bc->kind, BCON::kFixV) )  nd->v.V = bc->val->V;
          }

#         ifdef kDebug
          sprintf( text,
                   "  %5d (UVhKDvt): %9.2le %9.2le %9.2le %9.2le %9.2le %9.2le\n",
                                  nd->Getname(),
                                  nd->v.U,
                                  nd->v.V,
                                  nd->v.S - nd->z,
                                  nd->v.K,
                                  nd->v.D,
                                  nd->vt );
          REPORT::rpt.Output( text, 5 );

#         else

          sprintf( text, "  %5d", nd->Getname() );
          REPORT::rpt.Output( text, 5 );

          l++;
          if( !( l % 10) )  REPORT::rpt.Output( "\n", 5 );
#         endif

          m++;
        }

        else
        {
          nd->v.U = 0.0;
          nd->v.V = 0.0;
          nd->v.K = 0.0;
          nd->v.D = 0.0;
          nd->v.S = nd->z;
        }
      }

      nd->mark = false;
    }

#   ifndef kDebug
    if( l % 10 )
      REPORT::rpt.Output( "\n", 5 );
#   endif


    // rewet all dry elements without dry nodes ------------------------------------------

    for( int e=0; e<Getne(); e++ )
    {
      ELEM* el = Getelem(e);

      if( isFS(el->flag, ELEM::kDry) )
      {
        nnd = el->Getnnd();

        rewetFlag = true;

        for( j=0; j<nnd; j++ )
        {
          if( isFS(el->nd[j]->flag, NODE::kDry) )
          {
            rewetFlag = false;
            break;
          }
        }

        if( rewetFlag )
        {
          CF( el->flag, ELEM::kDry );
        }
      }
    }
  }


  // loop on all elements: all nodes at wet elements are wet -----------------------------

  for( int n=0; n<Getnp(); n++ )
  {
    NODE* nd = Getnode(n);

    SF( nd->flag, NODE::kDry );

    nd->mark = false;
  }


  for( int e=0; e<Getne(); e++ )
  {
    ELEM* el = Getelem(e);

    if( !isFS(el->flag, ELEM::kDry) )
    {
      nnd = el->Getnnd();

      for( j=0; j<nnd; j++ )  CF( el->nd[j]->flag, NODE::kDry );
    }
  }


  for( int n=0; n<Getnp(); n++ )
  {
    NODE* nd = Getnode(n);

    if( isFS(nd->flag, NODE::kDry) )
    {
      nd->v.U = 0.0;
      nd->v.V = 0.0;
      nd->v.K = 0.0;
      nd->v.D = 0.0;
      nd->v.S = nd->z;
    }
  }



  // report elements which have been rewetted --------------------------------------------

  REPORT::rpt.Output( "\n (rewet)         the following elements have been rewetted\n", 5 );

  l  = 0;
  for( int e=0; e<Getne(); e++ )
  {
    ELEM* el = Getelem(e);

    nnd = el->Getnnd();

    if( el->mark  &&  !isFS(el->flag, ELEM::kDry) )
    {
      for( j=0; j<nnd; j++ )
      {
        if( isFS(el->nd[j]->flag, NODE::kDry) )
          REPORT::rpt.Error ("unexpected error - rewet (1)");
      }

      sprintf( text, "  %5d", el->Getname() );
      REPORT::rpt.Output( text, 5 );

      l++;
      if( !( l % 10) )  REPORT::rpt.Output( "\n", 5 );
    }

    el->mark = false;
  }

  if( l % 10 )  REPORT::rpt.Output( "\n", 5 );


# ifndef kDebug
  if( l % 10 )  REPORT::rpt.Output( "\n", 5 );
# endif


  return l;
}
Example #9
0
void EQS::Update( MODEL*  model,
                  SUBDOM* subdom,
                  double* X,
                  int     ind,
                  int     varInd,
                  double* maxAbs,
                  double* maxPer,
                  double* avAbs,
                  double* avPer,
                  int*    noAbs,
                  int*    noPer )
{
  *maxAbs = 0.0;
  *maxPer = 0.0;
  *avAbs  = 0.0;
  *avPer  = 0.0;

  *noAbs = -1;
  *noPer = -1;

  int countAbs = 0;
  int countPer = 0;

  for( int n=0; n<model->np; n++ )
  {
    NODE* nd = model->node[n];

    int eqno = GetEqno( nd, ind );

    if( eqno >= 0 )
    {
      double chAbs = fabs( X[eqno] );


      // absolute changes, maximum and on average

      *avAbs += chAbs;
      countAbs++;

      if( chAbs > *maxAbs )
      {
        *maxAbs = chAbs;
        *noAbs  = nd->Getname();
      }


      // percentage changes, maximum and on average

      double H = nd->v.S - nd->z;

      double val = 0.0;

      switch( varInd )
      {
        case kVarU:   val = nd->v.U;       break;
        case kVarV:   val = nd->v.V;       break;
        case kVarH:
        case kVarS:   val = H;             break;
        case kVarK:   val = nd->v.K;       break;
        case kVarD:   val = nd->v.D;       break;
        case kVarC:   val = nd->v.C;       break;
        case kVarQb:  val = nd->v.Qb;      break;
        case kVarDz:  val = nd->dz;        break;

        case kVarUH:  val = H * nd->v.U;   break;
        case kVarVH:  val = H * nd->v.V;   break;
      }

      if( fabs(val) > 1.0e-9 )
      {
        double chPer = chAbs / fabs(val);

        *avPer += fabs(chPer);
        countPer++;

        if( fabs(chPer) > fabs(*maxPer) )
        {
          *maxPer = chPer;
          *noPer  = nd->Getname();
        }
      }
    }
  }

  ////////////////////////////////////////////////////////////////////////////////////////
# ifdef _MPI_

  int    mpi_noAbs;
  int    mpi_noPer;
  double mpi_maxAbs;
  double mpi_maxPer;

  if( subdom->pid == 0 )
  {
    MPI_Status status;

    for( int s=1; s<subdom->npr; s++ )
    {
      MPI_Recv( &mpi_noAbs,  1, MPI_INT,    s, 1, MPI_COMM_WORLD, &status );
      MPI_Recv( &mpi_maxAbs, 1, MPI_DOUBLE, s, 2, MPI_COMM_WORLD, &status );

      if( mpi_maxAbs > *maxAbs )
      {
        *noAbs  = mpi_noAbs;
        *maxAbs = mpi_maxAbs;
      }

      MPI_Recv( &mpi_noPer,  1, MPI_INT,    s, 1, MPI_COMM_WORLD, &status );
      MPI_Recv( &mpi_maxPer, 1, MPI_DOUBLE, s, 2, MPI_COMM_WORLD, &status );

      if( fabs(mpi_maxPer) > fabs(*maxPer) )
      {
        *noPer  = mpi_noPer;
        *maxPer = mpi_maxPer;
      }
    }
  }
  else
  {
    MPI_Send( noAbs,  1, MPI_INT,    0, 1, MPI_COMM_WORLD );
    MPI_Send( maxAbs, 1, MPI_DOUBLE, 0, 2, MPI_COMM_WORLD );

    MPI_Send( noPer,  1, MPI_INT,    0, 1, MPI_COMM_WORLD );
    MPI_Send( maxPer, 1, MPI_DOUBLE, 0, 2, MPI_COMM_WORLD );
  }

  MPI_Bcast( noAbs,  1, MPI_INT,    0, MPI_COMM_WORLD );
  MPI_Bcast( maxAbs, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD );

  MPI_Bcast( noPer,  1, MPI_INT,    0, MPI_COMM_WORLD );
  MPI_Bcast( maxPer, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD );


  //*maxAbs  = subdom->Mpi_max( *maxAbs );
  countAbs = subdom->Mpi_sum( countAbs );
  *avAbs   = subdom->Mpi_sum( *avAbs );
# endif
  ////////////////////////////////////////////////////////////////////////////////////////

  *avAbs /= countAbs;

  if( countPer )  *avPer /= countPer;

  *avPer  *= 100.0;
  *maxPer *= 100.0;
}
Example #10
0
void MODEL::Boundary()
{
  char text[200];

  // initializations ---------------------------------------------------------------------

  if( !boundList )
  {
    boundList = new ELEM* [region->Getnp()];
    if( !boundList )
      REPORT::rpt.Error( kMemoryFault, "can not allocate memory - MODEL::Boundary(1)" );
  }

  for( int n=0; n<region->Getnp(); n++ )
  {
    NODE* nd = region->Getnode(n);

    CF( nd->flag, NODE::kBound );

    nd->mark = false;


    // remove slip boundary conditions ---------------------------------------------------

    if( isFS(nd->bc.kind, BCON::kAutoSlip) )
    {
      CF( nd->bc.kind, BCON::kAutoSlip | BCON::kFixU | BCON::kFixV );
    }

    if( isFS(nd->bc.kind, BCON::kAutoKD) )
    {
      CF( nd->bc.kind, BCON::kAutoKD | BCON::kFixK | BCON::kFixD );
    }
  }


  // determine boundary midside nodes ----------------------------------------------------

  for( int n=0; n<region->Getnp(); n++ )
  {
    NODE* nd = region->Getnode(n);

    // midside nodes which are connected to only one element are boundary nodes ----------

    if( nd->noel == 1  &&  isFS(nd->flag, NODE::kMidsNode) )
    {
      if( !isFS(nd->flag, NODE::kInface) )  SF( nd->flag, NODE::kBound );
    }
  }


  // determine number of boundary elements: nb -------------------------------------------

  int nb = 0;

  for( int n=0; n<region->Getnp(); n++ )
  {
    if( isFS(region->Getnode(n)->flag,NODE::kBound) )  nb++;
  }


  // allocate memory for boundary elements -----------------------------------------------

  bound->Free();
  bound->Alloc( 0, nb );


  // set up boundary elements ------------------------------------------------------------

  int be = 0;       // counter for boundary elements

  for( int re=0; re<region->Getne(); re++ )
  {
    ELEM* el = region->Getelem(re);

    if( isFS(el->flag, ELEM::kDry) )  continue;

    int ncn = el->Getncn();
    int nnd = el->Getnnd();

    for( int i=ncn; i<nnd; i++ )
    {
      // check, if el->nd[i] is a midside boundary node ----------------------------------

      if( isFS(el->nd[i]->flag, NODE::kBound) )
      {
        ELEM* bd = bound->Getelem(be);

        boundList[el->nd[i]->Getno()] = bd;

        int left = i - ncn;
        int rght = (left + 1) % ncn;

        bd->nd[0] = el->nd[left];           // corner nodes
        bd->nd[1] = el->nd[rght];
        bd->nd[2] = el->nd[i];              // midside node

        SF( bd->nd[0]->flag, NODE::kBound );
        SF( bd->nd[1]->flag, NODE::kBound );


        // set shape specifications ------------------------------------------------------

        bd->Setshape( kLine );
        bd->Setname( el->Getname() );

        SF( bd->flag, ELEM::kBound );

        bd->type     = el->type;
        bd->areaFact = 1.0;

        be++;
      }
    }
  }


  ////////////////////////////////////////////////////////////////////////////////////////
  // communicate boundary nodes

//# ifdef _MPI_DBG
//  REPORT::rpt.Output( " (MODEL::Boundary)       communication of boundary nodes", 1 );
//# endif

# ifdef _MPI_
  if( subdom->npr > 1 )
  {
    INFACE* inface = subdom->inface;

    // loop on all interfaces: exchange bound flag ---------------------------------------
    for( int s=0; s<subdom->npr; s++ )
    {
      MPI_Status status;

      int npinf = inface[s].np;

      if( npinf > 0 )
      {
        for( int n=0; n<npinf; n++ )
        {
          NODE* nd = inface[s].node[n];

          if( isFS(nd->flag, NODE::kBound) )  inface[s].sia1[n] = true;
          else                                inface[s].sia1[n] = false;
        }

        MPI_Sendrecv( inface[s].sia1, npinf, MPI_CHAR, s, 1,
                      inface[s].ria1, npinf, MPI_CHAR, s, 1,
                      MPI_COMM_WORLD, &status );

        for( int n=0; n<npinf; n++ )
        {
          NODE* nd = inface[s].node[n];
          if( inface[s].ria1[n] )  SF( nd->flag, NODE::kBound );
        }
      }
    }
  }
# endif
  ////////////////////////////////////////////////////////////////////////////////////////


  // -------------------------------------------------------------------------------------
  // count for newly required boundary conditions
  // note: (sc, 30.10.2004)
  // a boundary condition is needed for marsh-nodes in case of dry-rewet-method 3

  int nbc = 0;

  for( int n=0; n<region->Getnp(); n++ )
  {
    NODE* nd = region->Getnode(n);

    if( isFS(nd->flag, NODE::kBound) )  nbc++;
  }

  sprintf( text,"\n (MODEL::Boundary)       number of boundary elements: %d\n", nb );
  REPORT::rpt.Output( text, 3 );


# ifdef kDebug
{
  int pid;
  MPI_Comm_rank( MPI_COMM_WORLD, &pid );

  char fname[40];
  sprintf( fname, "bound_%02d.inp", pid+1 );

  FILE* id = fopen( fname, "w" );

  for( int n=0; n<region->Getnp(); n++ )
  {
    NODE* nd = region->Getnode(n);

    CF( nd->flag, NODE::kMarker );
  }


  for( int e=0; e<bound->Getne(); e++ )
  {
    ELEM* el = bound->Getelem(e);

    for( int i=0; i<el->getnnd(); i++ )
    {
      SF( el->nd[i]->flag, NODE::kMarker );
    }
  }


  int j = 0;

  for( int n=0; n<region->Getnp(); n++ )
  {
    NODE* nd = region->Getnode(n);

    if( isFS(nd->flag, NODE::kMarker) )  j++;
  }


  fprintf( id, "%6d  %6d   0   0   0\n", j, nb );


  for( int n=0; n<region->Getnp(); n++ )
  {
    NODE* nd = region->Getnode(n);

    if( isFS(nd->flag, NODE::kMarker) )
    {
      fprintf( id, "%6d  %17.9le  %17.9le  %17.9le\n",
                   nd->Getname(), nd->x, nd->y, nd->z );
    }
  }

  for( int e=0; e<bound->Getne(); e++ )
  {
    ELEM* el = bound->Getelem(e);

    fprintf( id, "%6d  %3d  line   %6d  %6d  %6d\n",
                 el->Getname(), TYPE::getid(el->type),
                 el->nd[0]->Getname(), el->nd[1]->Getname(), el->nd[2]->Getname() );
  }

  fclose( id );
}
# endif
}