/[escript]/trunk/paso/src/SolverFCT_solve.c
ViewVC logotype

Diff of /trunk/paso/src/SolverFCT_solve.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1670 by ksteube, Thu Jul 24 04:30:43 2008 UTC revision 1804 by gross, Wed Sep 24 07:52:19 2008 UTC
# Line 4  Line 4 
4   *   *
5   *       Copyright 2007,2008 by University of Queensland   *       Copyright 2007,2008 by University of Queensland
6   *   *
7   *                http://esscc.uq.edu_m.au   *                http://esscc.uq.edu.au
8   *        Primary Business: Queensland, Australia   *        Primary Business: Queensland, Australia
9   *  Licensed under the Open Software License version 3.0   *  Licensed under the Open Software License version 3.0
10   *     http://www.opensource.org/licenses/osl-3.0.php   *     http://www.opensource.org/licenses/osl-3.0.php
# Line 23  Line 23 
23  */  */
24  /**************************************************************/  /**************************************************************/
25    
26  /* Author: l.gross@uq.edu_m.au */  /* Author: l.gross@uq.edu.au */
27    
28  /**************************************************************/  /**************************************************************/
29    
30  #include "Paso.h"  #include "Paso.h"
31  #include "Solver.h"  #include "Solver.h"
32  #include "SolverFCT.h"  #include "SolverFCT.h"
33    #include "PasoUtil.h"
34  #include "escript/blocktimer.h"  #include "escript/blocktimer.h"
35  #ifdef _OPENMP  #ifdef _OPENMP
36  #include <omp.h>  #include <omp.h>
# Line 38  Line 39 
39  #include <mpi.h>  #include <mpi.h>
40  #endif  #endif
41    
42    void Paso_SolverFCT_solve(Paso_FCTransportProblem* fctp, double* u, double dt, double* source, Paso_Options* options) {
43       const dim_t FAILURES_MAX=5;
44       err_t error_code;
45       dim_t m,n_substeps, i_substeps, Failed, i, iter;
46       err_t errorCode;
47       double *z_m=NULL, *b_n=NULL, *sourceP=NULL, *sourceN=NULL, *uTilde_n=NULL, *QN_n=NULL, *QP_n=NULL, *RN_m=NULL, *RP_m=NULL, *du_m=NULL;
48       Paso_Coupler *QN_n_coupler=NULL, *QP_n_coupler=NULL, *RN_m_coupler=NULL, *RP_m_coupler=NULL, *uTilde_n_coupler=NULL, *u_m_coupler=NULL;
49       Paso_SystemMatrix *flux_matrix_m=NULL;
50       double dt_max, dt2,t, norm_u_m, omega, norm_du_m, tol;
51       register double mass, rtmp;
52       const dim_t n=Paso_SystemMatrix_getTotalNumRows(fctp->transport_matrix);
53       dim_t blockSize=Paso_FCTransportProblem_getBlockSize(fctp);
54       const double atol=options->absolute_tolerance;  
55       const double rtol=options->tolerance;
56       const dim_t max_m=options->iter_max;
57       Paso_Performance pp;
58       bool_t converged=FALSE, max_m_reached=FALSE;
59       if (dt<=0.) {
60           Paso_setError(TYPE_ERROR,"Paso_SolverFCT_solve: dt must be positive.");
61       }
62       dt_max=Paso_FCTransportProblem_getSafeTimeStepSize(fctp);
63       /*
64        *  allocate memory
65        *
66        */
67       z_m=TMPMEMALLOC(n,double);
68       Paso_checkPtr(z_m);
69       du_m=TMPMEMALLOC(n,double);
70       Paso_checkPtr(du_m);
71       b_n=TMPMEMALLOC(n,double);
72       Paso_checkPtr(b_n);
73       sourceP=TMPMEMALLOC(n,double);
74       Paso_checkPtr(sourceP);
75       sourceN=TMPMEMALLOC(n,double);
76       Paso_checkPtr(sourceN);
77       uTilde_n=TMPMEMALLOC(n,double);
78       Paso_checkPtr(uTilde_n);
79       QN_n=TMPMEMALLOC(n,double);
80       Paso_checkPtr(QN_n);
81       QP_n=TMPMEMALLOC(n,double);
82       Paso_checkPtr(QP_n);
83       RN_m=TMPMEMALLOC(n,double);
84       Paso_checkPtr(RN_m);
85       RP_m=TMPMEMALLOC(n,double);
86       Paso_checkPtr(RP_m);
87       QN_n_coupler=Paso_Coupler_alloc(Paso_FCTransportProblem_borrowConnector(fctp),blockSize);
88       QP_n_coupler=Paso_Coupler_alloc(Paso_FCTransportProblem_borrowConnector(fctp),blockSize);
89       RN_m_coupler=Paso_Coupler_alloc(Paso_FCTransportProblem_borrowConnector(fctp),blockSize);
90       RP_m_coupler=Paso_Coupler_alloc(Paso_FCTransportProblem_borrowConnector(fctp),blockSize);
91       uTilde_n_coupler=Paso_Coupler_alloc(Paso_FCTransportProblem_borrowConnector(fctp),blockSize);
92       u_m_coupler=Paso_Coupler_alloc(Paso_FCTransportProblem_borrowConnector(fctp),blockSize);
93       flux_matrix_m=Paso_SystemMatrix_alloc(fctp->transport_matrix->type,
94                                                     fctp->transport_matrix->pattern,
95                                                     fctp->transport_matrix->row_block_size,
96                                                     fctp->transport_matrix->col_block_size);
97    
98       if (Paso_noError()) {
99           /*
100            *    Preparation:
101            *
102            */
103           Paso_FCT_setSource(n, source, sourceN, sourceP);
104           /*
105            * let the show begin!!!!
106            *
107            */
108            t=0;
109            i_substeps=0;
110            Paso_Copy(n,u,fctp->u);
111            norm_u_m=Paso_lsup(n,u, fctp->mpi_info);
112            /* while(i_substeps<n_substeps && Paso_noError()) { */
113            if (fctp->dt_max < LARGE_POSITIVE_FLOAT) {
114                dt2=MIN(dt_max,dt);
115            } else {
116                 dt2=dt;
117            }
118            while(t<dt && Paso_noError()) {
119                printf("substep step %ld at t=%e (step size= %e)\n",i_substeps+1,t+dt2,dt2);
120                Paso_FCT_setUp(fctp,dt2,sourceN,sourceP,b_n,uTilde_n,uTilde_n_coupler,QN_n,QN_n_coupler,QP_n,QP_n_coupler,
121                               options,&pp);
122                /* now the iteration starts */
123                m=0;
124                converged=FALSE;
125                max_m_reached=FALSE;
126                /* tolerance? */
127                while ( (!converged) && (! max_m_reached) && Paso_noError()) {
128                        /* set z_m */
129                        Paso_FCT_setUpRightHandSide(fctp,dt2,u,u_m_coupler,z_m,flux_matrix_m,uTilde_n_coupler,b_n,
130                                      QN_n_coupler,QP_n_coupler,RN_m,RN_m_coupler,RP_m,RP_m_coupler,sourceN,&pp);
131                        /*
132                         * now we solve the linear system to get the correction dt:
133                         *
134                         */
135                         if (fctp->theta > 0) {
136                              omega=1./(dt2*fctp->theta);
137                              Paso_Solver_solvePreconditioner(fctp->iteration_matrix,du_m,z_m);  
138                              Paso_Update(n,1.,u,omega,du_m);
139                         } else {
140                              omega=1;
141                              #pragma omp parallel for private(i,mass,rtmp)
142                              for (i = 0; i < n; ++i) {
143                                  mass=fctp->lumped_mass_matrix[i];
144                                  if (ABS(mass)>0.) {
145                                      rtmp=z_m[i]/mass;
146                                  } else {
147                                      rtmp=0;
148                                  }
149                                  du_m[i]=rtmp;
150                                  u[i]+=rtmp;
151                              }
152                       }
153                       norm_u_m=Paso_lsup(n,u, fctp->mpi_info);
154                       norm_du_m=Paso_lsup(n,du_m, fctp->mpi_info)*omega;
155                       printf("iteration step %ld completed: norm increment= %e (tolerance = %e)\n",m+1, norm_du_m, rtol * norm_u_m + atol);
156    
157                       max_m_reached=(m>max_m);
158                       converged=(norm_du_m <= rtol * norm_u_m + atol);
159                       m++;
160                }
161                if (converged) {
162                        Failed=0;
163                        #pragma omp parallel for schedule(static) private(i)
164                        Paso_Copy(n,fctp->u,u);
165                        i_substeps++;
166                        t+=dt2;
167                        if (fctp->dt_max < LARGE_POSITIVE_FLOAT) {
168                           dt2=MIN3(dt_max,dt2*1.5,dt-t);
169                        } else {
170                           dt2=MIN(dt2*1.5,dt-t);
171                        }
172                } else if (max_m_reached) {
173                        /* if FAILURES_MAX failures in a row: give up */
174                        if (Failed > FAILURES_MAX) {
175                           Paso_setError(VALUE_ERROR,"Paso_SolverFCT_solve: no convergence after time step reduction.");
176                        } else {
177                           printf("no convergence in Paso_Solver_NewtonGMRES: Trying smaller time step size.");
178                           dt2=dt*0.5;
179                           Failed++;
180                        }
181                }
182            
183          }
184          /*
185           *  clean-up:
186           *
187           */
188          MEMFREE(z_m);
189          MEMFREE(du_m);
190          TMPMEMFREE(b_n);
191          Paso_SystemMatrix_free(flux_matrix_m);
192          TMPMEMFREE(sourceP);
193          TMPMEMFREE(sourceN);
194          TMPMEMFREE(uTilde_n);
195          TMPMEMFREE(QN_n);
196          TMPMEMFREE(QP_n);
197          TMPMEMFREE(RN_m);
198          TMPMEMFREE(RP_m);
199          Paso_Coupler_free(QN_n_coupler);
200          Paso_Coupler_free(QP_n_coupler);
201          Paso_Coupler_free(RN_m_coupler);
202          Paso_Coupler_free(RP_m_coupler);
203          Paso_Coupler_free(uTilde_n_coupler);
204          Paso_Coupler_free(u_m_coupler);
205          options->absolute_tolerance=atol;
206          options->tolerance=rtol;
207       }
208    }
209  double Paso_FCTransportProblem_getSafeTimeStepSize(Paso_FCTransportProblem* fctp)  double Paso_FCTransportProblem_getSafeTimeStepSize(Paso_FCTransportProblem* fctp)
210  {  {
211     dim_t i, n_rows;     dim_t i, n;
212     double dt_max, dt_max_loc;     double dt_max, dt_max_loc;
213     register double rtmp1,rtmp2;     register double l_ii,m;
214     n_rows=Paso_SystemMatrix_getTotalNumRows(fctp->transport_matrix);     n=Paso_SystemMatrix_getTotalNumRows(fctp->transport_matrix);
215     if (! fctp->valid_matrices) {     if (! fctp->valid_matrices) {
216          fctp->dt_max=LARGE_POSITIVE_FLOAT;          fctp->dt_max=LARGE_POSITIVE_FLOAT;
217          /* extract the row sum of the advective part */          /* extract the row sum of the advective part */
# Line 59  double Paso_FCTransportProblem_getSafeTi Line 227  double Paso_FCTransportProblem_getSafeTi
227              #pragma omp parallel private(dt_max_loc)              #pragma omp parallel private(dt_max_loc)
228              {              {
229                 dt_max_loc=LARGE_POSITIVE_FLOAT;                 dt_max_loc=LARGE_POSITIVE_FLOAT;
230                 #pragma omp for schedule(static) private(i,rtmp1,rtmp2)                 #pragma omp for schedule(static) private(i,l_ii,m)
231                 for (i=0;i<n_rows;++i) {                 for (i=0;i<n;++i) {
232                      rtmp1=fctp->main_diagonal_low_order_transport_matrix[i];                      l_ii=fctp->main_diagonal_low_order_transport_matrix[i];
233                      rtmp2=fctp->lumped_mass_matrix[i];                      m=fctp->lumped_mass_matrix[i];
234                      if ( (rtmp1<0 && rtmp2>0.) || (rtmp1>0 && rtmp2<0) ) {                      if ( (l_ii<0 && m>0.) || (l_ii>0 && m<0) ) {
235                          dt_max_loc=MIN(dt_max_loc,-rtmp2/rtmp1);                          dt_max_loc=MIN(dt_max_loc,-m/l_ii);
236                      }                      }
237                  }                  }
238                  #pragma omp critical                  #pragma omp critical
# Line 88  double Paso_FCTransportProblem_getSafeTi Line 256  double Paso_FCTransportProblem_getSafeTi
256     }     }
257     return fctp->dt_max;     return fctp->dt_max;
258  }  }
259    /*
260     * inserts the source term into the problem
261     */
262    err_t Paso_FCT_setSource(const dim_t n,const double *source, double* sourceN, double* sourceP)
263  void Paso_SolverFCT_solve(Paso_FCTransportProblem* fctp, double* u, double dt, double* source, Paso_Options* options) {  {
264     index_t i;     dim_t i;
265     long n_substeps,n, m;     register double rtmp;
    double dt_max, omega, dt2,t;  
    double local_norm_u,local_norm_du,norm_u,norm_du, tolerance;  
    register double rtmp1,rtmp2,rtmp3,rtmp4, rtmp;  
    double *b_n=NULL, *sourceP=NULL, *sourceN=NULL, *uTilde_n=NULL, *QN_n=NULL, *QP_n=NULL, *RN_m=NULL, *RP_m=NULL, *z_m=NULL, *du_m=NULL,*u_m=NULL;  
    Paso_Coupler* QN_n_coupler=NULL, *QP_n_coupler=NULL, *uTilde_n_coupler=NULL, *RN_m_coupler=NULL, *RP_m_coupler=NULL, *u_m_coupler=NULL;  
    Paso_SystemMatrix *flux_matrix=NULL;  
    dim_t n_rows=Paso_SystemMatrix_getTotalNumRows(fctp->transport_matrix);  
    bool_t converged;  
    dim_t max_m=500;  
    double inner_tol=1.e-2;  
    dim_t blockSize=Paso_FCTransportProblem_getBlockSize(fctp);  
    if (dt<=0.) {  
        Paso_setError(TYPE_ERROR,"Paso_SolverFCT_solve: dt must be positive.");  
    }  
    dt_max=Paso_FCTransportProblem_getSafeTimeStepSize(fctp);  
266     /*     /*
267      *  allocate memory      * seperate source into positive and negative part:
     *  
268      */      */
269     u_m=TMPMEMALLOC(n_rows,double);     #pragma omp parallel for private(i,rtmp)
270     Paso_checkPtr(u_m);     for (i = 0; i < n; ++i) {
271     b_n=TMPMEMALLOC(n_rows,double);         rtmp=source[i];
272     Paso_checkPtr(b_n);         if (rtmp <0) {
273     sourceP=TMPMEMALLOC(n_rows,double);            sourceN[i]=-rtmp;
274     Paso_checkPtr(sourceP);            sourceP[i]=0;
    sourceN=TMPMEMALLOC(n_rows,double);  
    Paso_checkPtr(sourceN);  
    uTilde_n=TMPMEMALLOC(n_rows,double);  
    Paso_checkPtr(uTilde_n);  
    QN_n=TMPMEMALLOC(n_rows,double);  
    Paso_checkPtr(QN_n);  
    QP_n=TMPMEMALLOC(n_rows,double);  
    Paso_checkPtr(QP_n);  
    RN_m=TMPMEMALLOC(n_rows,double);  
    Paso_checkPtr(RN_m);  
    RP_m=TMPMEMALLOC(n_rows,double);  
    Paso_checkPtr(RP_m);  
    z_m=TMPMEMALLOC(n_rows,double);  
    Paso_checkPtr(z_m);  
    du_m=TMPMEMALLOC(n_rows,double);  
    Paso_checkPtr(du_m);  
    QN_n_coupler=Paso_Coupler_alloc(Paso_FCTransportProblem_borrowConnector(fctp),blockSize);  
    QP_n_coupler=Paso_Coupler_alloc(Paso_FCTransportProblem_borrowConnector(fctp),blockSize);  
    RN_m_coupler=Paso_Coupler_alloc(Paso_FCTransportProblem_borrowConnector(fctp),blockSize);  
    RP_m_coupler=Paso_Coupler_alloc(Paso_FCTransportProblem_borrowConnector(fctp),blockSize);  
    uTilde_n_coupler=Paso_Coupler_alloc(Paso_FCTransportProblem_borrowConnector(fctp),blockSize);  
    u_m_coupler=Paso_Coupler_alloc(Paso_FCTransportProblem_borrowConnector(fctp),blockSize);  
    flux_matrix=Paso_SystemMatrix_alloc(fctp->transport_matrix->type,  
                                        fctp->transport_matrix->pattern,  
                                        fctp->transport_matrix->row_block_size,  
                                        fctp->transport_matrix->col_block_size);  
    if (Paso_noError()) {  
        #ifdef PASO_MPI  
          double local_norm[2], norm[2];  
        #endif  
        /*  
         *    Preparation:  
         *  
         */  
       
        /* decide on substepping */  
        if (fctp->dt_max < LARGE_POSITIVE_FLOAT) {  
           n_substeps=(long)ceil(dt/dt_max);  
275         } else {         } else {
276            n_substeps=1;            sourceN[i]= 0;
277              sourceP[i]= rtmp;
278         }         }
279         dt2=dt/n_substeps;     }
280         printf("%ld time steps of size is %e (theta = %e, dt_max=%e).\n",n_substeps, dt2,fctp->theta, dt_max);  }
281         /*  err_t Paso_FCT_setUp(Paso_FCTransportProblem* fctp, const double dt, const double *sourceN, const double *sourceP, double* b, double* uTilde,
282      * seperate source into positive and negative part:                       Paso_Coupler* uTilde_coupler, double *QN, Paso_Coupler* QN_coupler, double *QP, Paso_Coupler* QP_coupler,
283      */                       Paso_Options* options, Paso_Performance* pp)
284          #pragma omp parallel for private(i,rtmp)  {
285          for (i = 0; i < n_rows; ++i) {     dim_t i;
286            rtmp=source[i];     const dim_t n=Paso_SystemMatrix_getTotalNumRows(fctp->transport_matrix);
287            if (rtmp <0) {     double omega, factor;
288               sourceN[i]=-rtmp;     register double m, u_tilde_i, rtmp4;
289               sourceP[i]=0;     /* distribute u */
290            } else {     Paso_Coupler_startCollect(fctp->u_coupler,fctp->u);
291               sourceN[i]= 0;     Paso_Coupler_finishCollect(fctp->u_coupler);
292               sourceP[i]= rtmp;     /*
293            }      * b^n[i]=m u^n[i] + dt*(1-theta) sum_{j <> i} l_{ij}*(u^n[j]-u^n[i]) + dt*sourceP[i]
294        *
295        * note that iteration_matrix stores the negative values of the
296        * low order transport matrix l therefore a=-dt*(1-fctp->theta) is used.
297        *
298        */
299        Paso_SolverFCT_setMuPaLuPbQ(b,fctp->lumped_mass_matrix,fctp->u_coupler,
300                                   -dt*(1-fctp->theta),fctp->iteration_matrix,dt,sourceP);
301       /*
302        *   uTilde[i]=b[i]/m[i]
303        *
304        *   fctp->iteration_matrix[i,i]=m[i]/(dt theta) + \frac{1}{\theta} \frac{q^-[i]}-l[i,i]
305        *
306        */
307        if (fctp->theta > 0) {
308             Paso_solve_free(fctp->iteration_matrix);
309             omega=1./(dt*fctp->theta);
310             factor=dt*omega;
311             #pragma omp parallel for private(i,m,u_tilde_i,rtmp4)
312             for (i = 0; i < n; ++i) {
313                  m=fctp->lumped_mass_matrix[i];
314                  if (ABS(m)>0.) {
315                     u_tilde_i=b[i]/m;
316                  } else {
317                     u_tilde_i=fctp->u[i];
318                  }
319                  rtmp4=m*omega-fctp->main_diagonal_low_order_transport_matrix[i];
320                  if (ABS(u_tilde_i)>0) rtmp4+=sourceN[i]*factor/u_tilde_i;
321                  fctp->iteration_matrix->mainBlock->val[fctp->main_iptr[i]]=rtmp4;
322                  uTilde[i]=u_tilde_i;
323             }
324             Performance_startMonitor(pp,PERFORMANCE_PRECONDITIONER_INIT);
325             Paso_Solver_setPreconditioner(fctp->iteration_matrix,options);
326             Performance_stopMonitor(pp,PERFORMANCE_PRECONDITIONER_INIT);
327        } else {
328            #pragma omp parallel for private(i,m,u_tilde_i)
329            for (i = 0; i < n; ++i) {
330                m=fctp->lumped_mass_matrix[i];
331                if (ABS(m)>0.) {
332                    u_tilde_i=b[i]/m;
333                } else {
334                    u_tilde_i=fctp->u[i];
335                }
336                uTilde[i]=u_tilde_i;
337          }          }
338          u_m_coupler->data=u_m;          /* no update of iteration_matrix required! */
339  /*        for (i = 0; i < n_rows; ++i) printf("%d : %e \n",i,source[i],sourceP[i],sourceN[i]) */      } /* end (fctp->theta > 0) */
         /*  
          * let the show begin!!!!  
          *  
          */  
         t=dt2;  
         n=0;  
         tolerance=options->tolerance;  
         while(n<n_substeps && Paso_noError()) {  
   
             printf("substep step %ld at t=%e\n",n+1,t);  
             /*  
              * b^n[i]=m u^n[i] + dt2*(1-theta) sum_{j <> i} l_{ij}*(u^n[j]-u^n[i]) + dt2*sourceP[i]  
              *  
              * note that iteration_matrix stores the negative values of the  
              * low order transport matrix l therefore a=-dt2*(1-fctp->theta) is used.  
              *  
              */  
              Paso_SolverFCT_setMuPaLuPbQ(b_n,fctp->lumped_mass_matrix,fctp->u_coupler,  
                                           -dt2*(1-fctp->theta),fctp->iteration_matrix,dt2,sourceP);  
              /*  
           *   uTilde_n[i]=b[i]/m[i]  
           *  
           *   fctp->iteration_matrix[i,i]=m[i]/(dt2 theta) + \frac{1}{\theta} \frac{q^-[i]}-l[i,i]  
           *  
           */  
              if (fctp->theta > 0) {  
                  Paso_solve_free(fctp->iteration_matrix);  
                  omega=1./(dt2*fctp->theta);  
                  rtmp2=dt2*omega;  
                  #pragma omp parallel for private(i,rtmp,rtmp3,rtmp4)  
                  for (i = 0; i < n_rows; ++i) {  
                       rtmp=fctp->lumped_mass_matrix[i];  
                       if (ABS(rtmp)>0.) {  
                          rtmp3=b_n[i]/rtmp;  
                       } else {  
                          rtmp3=fctp->u[i];  
                       }  
                       rtmp4=rtmp*omega-fctp->main_diagonal_low_order_transport_matrix[i];  
                       if (ABS(rtmp3)>0) rtmp4+=sourceN[i]*rtmp2/rtmp3;  
                       fctp->iteration_matrix->mainBlock->val[fctp->main_iptr[i]]=rtmp4;  
                       uTilde_n[i]=rtmp3;  
                  }  
              } else {  
                  #pragma omp parallel for private(i,rtmp,rtmp3)  
                  for (i = 0; i < n_rows; ++i) {  
                       rtmp=fctp->lumped_mass_matrix[i];  
                       if (ABS(rtmp)>0.) {  
                          rtmp3=b_n[i]/rtmp;  
                       } else {  
                          rtmp3=fctp->u[i];  
                       }  
                       uTilde_n[i]=rtmp3;  
                  }  
                  omega=1.;  
                  /* no update of iteration_matrix required! */  
              } /* end (fctp->theta > 0) */  
   
              /* distribute uTilde_n: */  
              Paso_Coupler_startCollect(uTilde_n_coupler,uTilde_n);  
              Paso_Coupler_finishCollect(uTilde_n_coupler);  
              /*  
               * calculate QP_n[i] max_{j} (\tilde{u}[j]- \tilde{u}[i] )  
               *           QN_n[i] min_{j} (\tilde{u}[j]- \tilde{u}[i] )  
               *  
               */  
               Paso_SolverFCT_setQs(uTilde_n_coupler,QN_n,QP_n,fctp->iteration_matrix);  
               Paso_Coupler_startCollect(QN_n_coupler,QN_n);  
               Paso_Coupler_startCollect(QP_n_coupler,QP_n);  
               Paso_Coupler_finishCollect(QN_n_coupler);  
               Paso_Coupler_finishCollect(QP_n_coupler);  
               /*  
                * now we enter the iteration on a time-step:  
                *  
                */  
                Paso_Coupler_copyAll(fctp->u_coupler, u_m_coupler);  
 /* REPLACE BY JACOBEAN FREE NEWTON */  
                m=0;  
                converged=FALSE;  
                while ( (!converged) && (m<max_m) && Paso_noError()) {  
                     printf("iteration step %ld\n",m+1);  
                     /*  
                      *  set the ant diffusion fluxes:  
                      *  
                     */  
                     Paso_FCTransportProblem_setAntiDiffusionFlux(dt2,fctp,flux_matrix,u_m_coupler);  
                     /*  
                      *  apply pre flux-correction: f_{ij}:=0 if f_{ij}*(\tilde{u}[i]- \tilde{u}[j])<=0  
                      *  
                      */  
                     Paso_FCTransportProblem_applyPreAntiDiffusionCorrection(flux_matrix,uTilde_n_coupler);  
                     /*  
                      *  set flux limiters RN_m,RP_m  
                      *  
                      */  
                     Paso_FCTransportProblem_setRs(flux_matrix,fctp->lumped_mass_matrix,QN_n_coupler,QP_n_coupler,RN_m,RP_m);  
                     Paso_Coupler_startCollect(RN_m_coupler,RN_m);  
                     Paso_Coupler_startCollect(RP_m_coupler,RP_m);  
                     /*  
                      * z_m[i]=b_n[i] - (m_i*u[i] - dt2*theta*sum_{j<>i} l_{ij} (u[j]-u[i]) + dt2 q^-[i])  
                      *  
                      * note that iteration_matrix stores the negative values of the  
                      * low order transport matrix l therefore a=dt2*fctp->theta is used.  
                      */  
340    
341                      Paso_SolverFCT_setMuPaLuPbQ(z_m,fctp->lumped_mass_matrix, u_m_coupler,      /* distribute uTilde: */
342                                                  dt2*fctp->theta,fctp->iteration_matrix,dt2,sourceN);      Paso_Coupler_startCollect(uTilde_coupler,uTilde);
343  /* for (i = 0; i < n_rows; ++i) {      Paso_Coupler_finishCollect(uTilde_coupler);
344  * printf("%d: %e %e\n",i,z_m[i], b_n[i]);      /*
345  * }       * calculate QP[i] max_{j} (\tilde{u}[j]- \tilde{u}[i] )
346  */       *           QN[i] min_{j} (\tilde{u}[j]- \tilde{u}[i] )
347                      #pragma omp parallel for private(i)       *
348                      for (i = 0; i < n_rows; ++i) z_m[i]=b_n[i]-z_m[i];       */
349         Paso_SolverFCT_setQs(uTilde_coupler,QN,QP,fctp->iteration_matrix);
350                      Paso_Coupler_finishCollect(RN_m_coupler);       Paso_Coupler_startCollect(QN_coupler,QN);
351                      Paso_Coupler_finishCollect(RP_m_coupler);       Paso_Coupler_startCollect(QP_coupler,QP);
352                      /* add corrected fluxes into z_m */       Paso_Coupler_finishCollect(QN_coupler);
353                      Paso_FCTransportProblem_addCorrectedFluxes(z_m,flux_matrix,RN_m_coupler,RP_m_coupler);       Paso_Coupler_finishCollect(QP_coupler);
354                      /*  }
355                        * now we solve the linear system to get the correction dt2:  err_t Paso_FCT_setUpRightHandSide(Paso_FCTransportProblem* fctp, const double dt, const double *u_m, Paso_Coupler* u_m_coupler,  double * z_m,
356                        *                                    Paso_SystemMatrix* flux_matrix, Paso_Coupler* uTilde_coupler, const double *b,
357                       */                                    Paso_Coupler* QN_coupler, Paso_Coupler* QP_coupler,
358                      if (fctp->theta > 0) {                                    double *RN_m, Paso_Coupler* RN_m_coupler, double* RP_m, Paso_Coupler* RP_m_coupler, const double *sourceN,
359                              /*  set the right hand side of the linear system: */                                    Paso_Performance* pp)
360                              options->tolerance=inner_tol;  {
361                              options->verbose=TRUE;     dim_t i;
362                              Paso_solve(fctp->iteration_matrix,du_m,z_m,options);     const dim_t n=Paso_SystemMatrix_getTotalNumRows(fctp->transport_matrix);
363                              /* TODO: check errors ! */     register double m, rtmp;
364                        } else {     /* distribute u */
365                              #pragma omp parallel for private(i,rtmp,rtmp1)     Paso_Coupler_startCollect(u_m_coupler,u_m);
366                              for (i = 0; i < n_rows; ++i) {     Paso_Coupler_finishCollect(u_m_coupler);
367                                  rtmp=fctp->lumped_mass_matrix[i];     /*
368                                  if (ABS(rtmp)>0.) {      *  set the ant diffusion fluxes:
369                                     rtmp1=z_m[i]/rtmp;      *
370                                  } else {      */
371                                     rtmp1=0;     Paso_FCTransportProblem_setAntiDiffusionFlux(dt,fctp,flux_matrix,u_m_coupler);
372                                  }     /*
373                                  du_m[i]=rtmp1;      *  apply pre flux-correction: f_{ij}:=0 if f_{ij}*(\tilde{u}[i]- \tilde{u}[j])<=0
374                              }      *
375                        }      */
376                        /*     Paso_FCTransportProblem_applyPreAntiDiffusionCorrection(flux_matrix,uTilde_coupler);
377                         * update u and calculate norm of du_m and the new u:     /*
378                         *      *  set flux limiters RN_m,RP_m
379                         */      *
380                         norm_u=0.;      */
381                         norm_du=0.;     Paso_FCTransportProblem_setRs(flux_matrix,fctp->lumped_mass_matrix,QN_coupler,QP_coupler,RN_m,RP_m);
382                         #pragma omp parallel private(local_norm_u,local_norm_du)     Paso_Coupler_startCollect(RN_m_coupler,RN_m);
383                         {     Paso_Coupler_startCollect(RP_m_coupler,RP_m);
384                             local_norm_u=0.;      /*
385                             local_norm_du=0.;       * z_m[i]=b[i] - (m_i*u_m[i] - dt*theta*sum_{j<>i} l_{ij} (u_m[j]-u_m[i]) + dt q^-[i])
386                             #pragma omp for schedule(static) private(i)       *
387                             for (i=0;i<n_rows;++i) {       * note that iteration_matrix stores the negative values of the
388                                  u_m[i]+=omega*du_m[i];       * low order transport matrix l therefore a=dt*fctp->theta is used.
389                                  local_norm_u=MAX(local_norm_u,ABS(u_m[i]));       */
390                                  local_norm_du=MAX(local_norm_du,ABS(du_m[i]));     Paso_SolverFCT_setMuPaLuPbQ(z_m,fctp->lumped_mass_matrix, u_m_coupler,dt*fctp->theta,fctp->iteration_matrix,dt,sourceN);
391                             }     /* z_m=b-z_m */
392                             #pragma omp critical     Paso_Update(n,-1.,z_m,1.,b);
393                             {  
394                                 norm_u=MAX(norm_u,local_norm_u);     Paso_Coupler_finishCollect(RN_m_coupler);
395                                 norm_du=MAX(norm_du,local_norm_du);     Paso_Coupler_finishCollect(RP_m_coupler);
396                             }     /* add corrected fluxes into z_m */
397                         }     Paso_FCTransportProblem_addCorrectedFluxes(z_m,flux_matrix,RN_m_coupler,RP_m_coupler);
398                         Paso_Coupler_startCollect(u_m_coupler,u_m);     return NO_ERROR;
                        #ifdef PASO_MPI  
                           local_norm[0]=norm_u;  
                           local_norm[1]=norm_du;  
                       MPI_Allreduce(local_norm,norm, 2, MPI_DOUBLE, MPI_MAX, fctp->mpi_info->comm);  
                           norm_u=norm[0];  
                           norm_du=norm[1];  
                        #endif  
                        norm_du*=omega;  
                        converged=(norm_du <= tolerance * norm_u);  
                        m++;  
                        printf("iteration step %ld: norm u and du_m : %e %e\n",m,norm_u,norm_du);  
                        /* TODO: check if du_m has been redu_mced */  
                        Paso_Coupler_finishCollect(u_m_coupler);  
                     } /* end of inner iteration */  
                     SWAP(fctp->u,u_m,double*);  
                     SWAP(fctp->u_coupler,u_m_coupler,Paso_Coupler*);  
                     n++;  
                } /* end of time integration */  
                options->tolerance=tolerance;  
                #pragma omp parallel for schedule(static) private(i)  
                for (i=0;i<n_rows;++i) u[i]=fctp->u[i];  
         }  
         /*  
          *  clean-up:  
          *  
          */  
         TMPMEMFREE(b_n);  
         Paso_SystemMatrix_free(flux_matrix);  
         TMPMEMFREE(sourceP);  
         TMPMEMFREE(sourceN);  
         TMPMEMFREE(uTilde_n);  
         TMPMEMFREE(QN_n);  
         TMPMEMFREE(QP_n);  
         TMPMEMFREE(RN_m);  
         TMPMEMFREE(RP_m);  
         TMPMEMFREE(z_m);  
         TMPMEMFREE(du_m);  
         TMPMEMFREE(u_m);  
         Paso_Coupler_free(QN_n_coupler);  
         Paso_Coupler_free(QP_n_coupler);  
         Paso_Coupler_free(RN_m_coupler);  
         Paso_Coupler_free(RP_m_coupler);  
         Paso_Coupler_free(uTilde_n_coupler);  
         Paso_Coupler_free(u_m_coupler);  
399  }  }

Legend:
Removed from v.1670  
changed lines
  Added in v.1804

  ViewVC Help
Powered by ViewVC 1.1.26