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

revision 1400 by gross, Thu Jan 24 06:04:31 2008 UTC revision 1661 by gross, Mon Jul 21 22:08:27 2008 UTC
# Line 2  Line 2
2
3  /*******************************************************  /*******************************************************
4   *   *
5   *       Copyright 2007 by University of Queensland   *       Copyright 2007,2008 by University of Queensland
6   *   *
7   *                http://esscc.uq.edu.au   *                http://esscc.uq.edu_m.au
# Line 15  Line 15
15
16  /* Paso: Flux correction transport solver  /* Paso: Flux correction transport solver
17   *   *
18   * solves Mu_t=Du+Ku+q   * solves Mu_t=Ku+q
19     *        u(0) >=0
20   *   *
21   *  where is D is diffusive (not checked)   * Warning: the program assums sum_{j} k_{ij}=0!!!
*          - D is symmetric
*          - row sums are equal to zero.
*  and  K is the advective part.
*
*        u(0) >= 0
*
* intially fctp->transport_matrix defines the diffusive part
* but the matrix is updated by the adevctive part + artificial diffusion
22   *   *
23  */  */
24  /**************************************************************/  /**************************************************************/
25
26  /* Author: l.gross@uq.edu.au */  /* Author: l.gross@uq.edu_m.au */
27
28  /**************************************************************/  /**************************************************************/
29
# Line 45  Line 38
38  #include <mpi.h>  #include <mpi.h>
39  #endif  #endif
40
41  /***********************************************************************************  double Paso_FCTransportProblem_getSafeTimeStepSize(Paso_FCTransportProblem* fctp)
42    {
43          solve (until convergence)     dim_t i, n_rows;
44       double dt_max, dt_max_loc;
45          (*)  [M-theta*dt*L] du = M*u_last + (1-theta)*dt*F(u_last) - M*u + theta*dt F(u)     register double rtmp1,rtmp2;
46               u <- u+du     n_rows=Paso_SystemMatrix_getTotalNumRows(fctp->transport_matrix);

with F(u) =  L u + f_a(u)  (f_a anti-diffusion)
and L = D + K + D_K  stored in transport_matrix
D = Diffusive part (on input stored in transport_matrix)
K = flux_matrix
D_K = artificial diffusion introduced by K
f_a = anti-diffusion introduced by K and u
u_last=u of last time step

For the case theta==0 (explicit case) no iteration is required. One sets

M*u= M*u_last + dt*b

with b=F(u) =  L u + f_a(u).

For the case theta>0 we solve (*) is the form

[L-M/theta*dt] du2 =M/(theta*dt)*u_last + ((1-theta)/theta)*F(u_last) - M/(theta*dt)*u + F(u)

for du2=-du which is solved as

A du2  = r= b + f(u)

with

du=-du2
A=L-M/(theta*dt) (stored into transport_matrix)
f(u) =-M/(theta*dt)*u + F(u) = - M/(theta*dt)*u + Lu + f_a(u) = f_a(u) + Au
F(u)=f(u)+M/(theta*dt)*u
b= M/(theta*dt)*u_last+(1-theta)/theta*F(u_last)=
= M/(theta*dt)*u_last+(1-theta)/theta*(f(u)+M/(theta*dt)*u_last)
= M/(theta*dt)*u_last+(1-theta)/theta*(f(u_last)+M/(theta*dt)*u_last)
= M*1./(theta*dt)*(1+(1-theta)/theta)*u_last+(1-theta)/theta*f(u_last)

*/

void Paso_SolverFCT_solve(Paso_FCTransportProblem* fctp, double* u, double dt, double* source, Paso_Options* options) {

index_t i, j;
int n_substeps,n, iter;
double fac, fac2, *b=NULL, *f=NULL, *du=NULL;
double dt2=fctp->dt_max, dt2_loc, rtmp,rtmp2,t;
double local_norm[2],norm[2],local_norm_u,local_norm_du,norm_u,norm_du, tolerance;
dim_t n_rows=Paso_SystemMatrix_getTotalNumRows(fctp->flux_matrix);
bool_t converged;
if (dt<=0.) {
Paso_setError(TYPE_ERROR,"Paso_SolverFCT_solve: dt must be positive.");
}
47     if (! fctp->valid_matrices) {     if (! fctp->valid_matrices) {
48            fctp->dt_max=LARGE_POSITIVE_FLOAT;
49          /* extract the row sum of the advective part */          /* extract the row sum of the advective part */
50          Paso_SystemMatrix_rowSum(fctp->flux_matrix,fctp->row_sum_flux_matrix);          Paso_SystemMatrix_rowSum(fctp->mass_matrix,fctp->lumped_mass_matrix);
/* add the advective part + artificial diffusion to the diffusive part = transport-matrix */
/* create a copy of the main diagonal entires of the transport-matrix */
#pragma omp parallel for schedule(static) private(i)
for (i=0;i<n_rows;++i) {
fctp->transport_matrix_diagonal[i]=
fctp->transport_matrix->mainBlock->val[fctp->main_iptr[i]];
}
51
52   /* Paso_SystemMatrix_saveMM(fctp->flux_matrix,"flux.mm");          /* set low order transport operator */
53   Paso_SystemMatrix_saveMM(fctp->transport_matrix,"trans.mm");  */          Paso_FCTransportProblem_setLowOrderOperator(fctp);
54          /*=================================================================== *          /*
*
55           *  calculate time step size:                                                     *  calculate time step size:
56           */          */
57          dt2=LARGE_POSITIVE_FLOAT;          dt_max=LARGE_POSITIVE_FLOAT;
58          if (fctp->theta < 1.) {          if (fctp->theta < 1.) {
59              #pragma omp parallel private(dt2_loc)              #pragma omp parallel private(dt_max_loc)
60              {              {
61                 dt2_loc=LARGE_POSITIVE_FLOAT;                 dt_max_loc=LARGE_POSITIVE_FLOAT;
62                 #pragma omp for schedule(static) private(i,rtmp,rtmp2)                 #pragma omp for schedule(static) private(i,rtmp1,rtmp2)
63                 for (i=0;i<n_rows;++i) {                 for (i=0;i<n_rows;++i) {
64                      rtmp=fctp->transport_matrix_diagonal[i];                      rtmp1=fctp->main_diagonal_low_order_transport_matrix[i];
65                      rtmp2=fctp->lumped_mass_matrix[i];                      rtmp2=fctp->lumped_mass_matrix[i];
66                      if ( (rtmp<0 && rtmp2>=0.) || (rtmp>0 && rtmp2<=0.) ) {                      if ( (rtmp1<0 && rtmp2>0.) || (rtmp1>0 && rtmp2<0) ) {
67                          dt2_loc=MIN(dt2_loc,-rtmp2/rtmp);                          dt_max_loc=MIN(dt_max_loc,-rtmp2/rtmp1);
68                      }                      }
69                  }                  }
70                  #pragma omp critical                  #pragma omp critical
71                  {                  {
72                      dt2=MIN(dt2,dt2_loc);                      dt_max=MIN(dt_max,dt_max_loc);
73                  }                  }
74              }              }
75              #ifdef PASO_MPI              #ifdef PASO_MPI
76                 dt2_loc = dt2;                 dt_max_loc = dt_max;
77             MPI_Allreduce(&dt2_loc, &dt2, 1, MPI_DOUBLE, MPI_MIN, fctp->mpi_info->comm);             MPI_Allreduce(&dt_max_loc, &dt_max, 1, MPI_DOUBLE, MPI_MIN, fctp->mpi_info->comm);
78              #endif               #endif
79              if (dt2<LARGE_POSITIVE_FLOAT) dt2*=1./(1.-fctp->theta);               if (dt_max<LARGE_POSITIVE_FLOAT) dt_max*=1./(1.-fctp->theta);
80          }           }
81          if (dt2 <= 0.) {           if (dt_max <= 0.)  {
82              Paso_setError(TYPE_ERROR,"Paso_SolverFCT_solve: dt must be positive.");              Paso_setError(TYPE_ERROR,"Paso_SolverFCT_solve: dt must be positive.");
83          } else {           } else {
84             if (dt2<LARGE_POSITIVE_FLOAT) printf("minimum time step size is %e (theta = %e).\n",dt2,fctp->theta);               if (dt_max<LARGE_POSITIVE_FLOAT) printf("maximum time step size is %e (theta = %e).\n",dt_max,fctp->theta);
85          }          }
86          fctp->dt=dt2;          fctp->dt_max=dt_max;
fctp->dt_max=dt2; /* FIXME: remove*/
87          fctp->valid_matrices=Paso_noError();          fctp->valid_matrices=Paso_noError();
88     }     }
89       return fctp->dt_max;
90    }
91
92
93
94
95     /* */  void Paso_SolverFCT_solve(Paso_FCTransportProblem* fctp, double* u, double dt, double* source, Paso_Options* options) {
96     Paso_SystemMatrix_allocBuffer(fctp->transport_matrix);     index_t i;
97       long n_substeps,n, m;
98       double dt_max, omega, dt2,t;
99       double local_norm_u,local_norm_du,norm_u,norm_du, tolerance;
100       register double rtmp1,rtmp2,rtmp3,rtmp4, rtmp;
101       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;
102       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;
103       Paso_SystemMatrix *flux_matrix=NULL;
104       dim_t n_rows=Paso_SystemMatrix_getTotalNumRows(fctp->transport_matrix);
105       bool_t converged;
106       dim_t max_m=500;
107       double inner_tol=1.e-2;
108       dim_t blockSize=Paso_FCTransportProblem_getBlockSize(fctp);
109       if (dt<=0.) {
110           Paso_setError(TYPE_ERROR,"Paso_SolverFCT_solve: dt must be positive.");
111       }
112       dt_max=Paso_FCTransportProblem_getSafeTimeStepSize(fctp);
113     /*     /*
114      * allocate memory:      *  allocate memory
115      *      *
116      */      */
117     b=MEMALLOC(n_rows,double);     u_m=TMPMEMALLOC(n_rows,double);
118     Paso_checkPtr(b);     Paso_checkPtr(u_m);
119     if (fctp->theta>0) {     b_n=TMPMEMALLOC(n_rows,double);
120         b=MEMALLOC(n_rows,double);     Paso_checkPtr(b_n);
121         du=MEMALLOC(n_rows,double);     sourceP=TMPMEMALLOC(n_rows,double);
122         f=MEMALLOC(n_rows,double);     Paso_checkPtr(sourceP);
123         Paso_checkPtr(du);     sourceN=TMPMEMALLOC(n_rows,double);
124         Paso_checkPtr(f);     Paso_checkPtr(sourceN);
125     }     uTilde_n=TMPMEMALLOC(n_rows,double);
126       Paso_checkPtr(uTilde_n);
127       QN_n=TMPMEMALLOC(n_rows,double);
128       Paso_checkPtr(QN_n);
129       QP_n=TMPMEMALLOC(n_rows,double);
130       Paso_checkPtr(QP_n);
131       RN_m=TMPMEMALLOC(n_rows,double);
132       Paso_checkPtr(RN_m);
133       RP_m=TMPMEMALLOC(n_rows,double);
134       Paso_checkPtr(RP_m);
135       z_m=TMPMEMALLOC(n_rows,double);
136       Paso_checkPtr(z_m);
137       du_m=TMPMEMALLOC(n_rows,double);
138       Paso_checkPtr(du_m);
139       QN_n_coupler=Paso_Coupler_alloc(Paso_FCTransportProblem_borrowConnector(fctp),blockSize);
140       QP_n_coupler=Paso_Coupler_alloc(Paso_FCTransportProblem_borrowConnector(fctp),blockSize);
141       RN_m_coupler=Paso_Coupler_alloc(Paso_FCTransportProblem_borrowConnector(fctp),blockSize);
142       RP_m_coupler=Paso_Coupler_alloc(Paso_FCTransportProblem_borrowConnector(fctp),blockSize);
143       uTilde_n_coupler=Paso_Coupler_alloc(Paso_FCTransportProblem_borrowConnector(fctp),blockSize);
144       u_m_coupler=Paso_Coupler_alloc(Paso_FCTransportProblem_borrowConnector(fctp),blockSize);
145       flux_matrix=Paso_SystemMatrix_alloc(fctp->transport_matrix->type,
146                                           fctp->transport_matrix->pattern,
147                                           fctp->transport_matrix->row_block_size,
148                                           fctp->transport_matrix->col_block_size);
149     if (Paso_noError()) {     if (Paso_noError()) {
150         /*         /*
151          *    Preparation:          *    Preparation:
# Line 175  void Paso_SolverFCT_solve(Paso_FCTranspo Line 153  void Paso_SolverFCT_solve(Paso_FCTranspo
153          */          */
154
155         /* decide on substepping */         /* decide on substepping */
156         if (fctp->dt < LARGE_POSITIVE_FLOAT) {         if (fctp->dt_max < LARGE_POSITIVE_FLOAT) {
157            n_substeps=ceil(dt/fctp->dt);            n_substeps=(long)ceil(dt/dt_max);
158         } else {         } else {
159            n_substeps=1.;            n_substeps=1;
160         }         }
161         dt2=dt/n_substeps;         dt2=dt/n_substeps;
162         printf("%d time steps of size is %e (theta = %e, dt_max=%e).\n",n_substeps, dt2,fctp->theta,fctp->dt);         printf("%ld time steps of size is %e (theta = %e, dt_max=%e).\n",n_substeps, dt2,fctp->theta, dt_max);
163                   /*
164         /*      * seperate source into positive and negative part:
165          *  implicit case:      */
166          *          #pragma omp parallel for private(i,rtmp)
167          *   A=L-M/(theta*dt) (stored into transport_matrix)          for (i = 0; i < n_rows; ++i) {
168          *            rtmp=source[i];
169          * b= M/(theta*dt)*u_last+(1-theta)/theta)*F(u_last)              if (rtmp <0) {
170          *               sourceN[i]=-rtmp;
171          */               sourceP[i]=0;
172         if (fctp->theta>0) {            } else {
173            Paso_solve_free(fctp->transport_matrix);               sourceN[i]= 0;
174            fac=1./(fctp->theta*dt2);               sourceP[i]= rtmp;
fac2=(1.-fctp->theta)/fctp->theta;
#pragma omp parallel for schedule(static) private(i)
for (i=0;i<n_rows;++i) {
fctp->transport_matrix->mainBlock->val[fctp->main_iptr[i]]=
fctp->transport_matrix_diagonal[i]-fctp->lumped_mass_matrix[i]*fac;
175            }            }
176         }          }
177         #pragma omp parallel for schedule(static) private(i)          u_m_coupler->data=u_m;
178         for (i=0;i<n_rows;++i) {  /*        for (i = 0; i < n_rows; ++i) printf("%d : %e \n",i,source[i],sourceP[i],sourceN[i]) */
179           u[i]=fctp->u[i];          /*
180  /* printf("A %d : %e %e\n",i,u[i],fctp->u[i]); */           * let the show begin!!!!
181         }           *
182         /*           */
* now the show can begin:
*
*/
183          t=dt2;          t=dt2;
184          n=0;          n=0;
185          tolerance=options->tolerance;          tolerance=options->tolerance;
186          while(n<n_substeps && Paso_noError()) {          while(n<n_substeps && Paso_noError()) {
187              printf("substep step %d at t=%e\n",n+1,t);
188              if (fctp->theta>0.) {              printf("substep step %ld at t=%e\n",n+1,t);
189                  /*              /*
190                   * implicit scheme:               * b^n[i]=m u^n[i] + dt2*(1-theta) sum_{j <> i} l_{ij}*(u^n[j]-u^n[i]) + dt2*sourceP[i]
191                   *               *
192                   */               * note that iteration_matrix stores the negative values of the
193                  if (fctp->theta<1.) {               * low order transport matrix l therefore a=-dt2*(1-fctp->theta) is used.
194                     Paso_FCTransportProblem_setFlux(fctp,u,b);  /* b=f(u_last) */               *
195                     #pragma omp parallel for schedule(static) private(i)               */
196                     for (i=0;i<n_rows;++i) {               Paso_SolverFCT_setMuPaLuPbQ(b_n,fctp->lumped_mass_matrix,fctp->u_coupler,
197                          b[i]=fctp->lumped_mass_matrix[i]*fac*(1.+fac2)*u[i]+fac2*b[i];                                            -dt2*(1-fctp->theta),fctp->iteration_matrix,dt2,sourceP);
198                      }               /*
199                  } else {            *   uTilde_n[i]=b[i]/m[i]
200                     #pragma omp parallel for schedule(static) private(i)            *
201                     for (i=0;i<n_rows;++i) {            *   fctp->iteration_matrix[i,i]=m[i]/(dt2 theta) + \frac{1}{\theta} \frac{q^-[i]}-l[i,i]
202                         b[i]=fctp->lumped_mass_matrix[i]*fac*u[i];            *
203                     }            */
204                  }               if (fctp->theta > 0) {
205                  /*                   Paso_solve_free(fctp->iteration_matrix);
206                   * Enter iteration on a time step :                   omega=1./(dt2*fctp->theta);
207                   *                   rtmp2=dt2*omega;
208                   */                   #pragma omp parallel for private(i,rtmp,rtmp3,rtmp4)
209                   iter=0;                   for (i = 0; i < n_rows; ++i) {
210                   converged=FALSE;                        rtmp=fctp->lumped_mass_matrix[i];
211                   while ( (!converged) && (iter<50) && Paso_noError()) {                        if (ABS(rtmp)>0.) {
212                      printf("iteration step %d\n",iter+1);                           rtmp3=b_n[i]/rtmp;
213                      Paso_FCTransportProblem_setFlux(fctp,u,f);                        } else {
214                      #pragma omp parallel for schedule(static) private(i)                           rtmp3=fctp->u[i];
215                      for (i=0;i<n_rows;++i) {                        }
216                         f[i]+=b[i];                        rtmp4=rtmp*omega-fctp->main_diagonal_low_order_transport_matrix[i];
217                      }                        if (ABS(rtmp3)>0) rtmp4+=sourceN[i]*rtmp2/rtmp3;
218                      options->tolerance=1.e-3;                        fctp->iteration_matrix->mainBlock->val[fctp->main_iptr[i]]=rtmp4;
219                      Paso_solve(fctp->transport_matrix,du,f,options);                        uTilde_n[i]=rtmp3;
/* update u and calculate norms */
norm_u=0.;
norm_du=0.;
#pragma omp parallel private(local_norm_u,local_norm_du)
{
local_norm_u=0.;
local_norm_du=0.;
#pragma omp for schedule(static) private(i)
for (i=0;i<n_rows;++i) {
u[i]-=du[i];
local_norm_u=MAX(local_norm_u,ABS(u[i]));
local_norm_du=MAX(local_norm_du,ABS(du[i]));
}
#pragma omp crtical
{
norm_u=MAX(norm_u,local_norm_u);
norm_du=MAX(norm_du,local_norm_du);
}
}
#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
converged=(norm_du <= tolerance * norm_u);
iter++;
printf("iteration step %d: norm u and du : %e %e\n",iter,norm_u,norm_du);
220                   }                   }
221               } else {               } else {
222                  /*                   #pragma omp parallel for private(i,rtmp,rtmp3)
223                    * explicit scheme:                   for (i = 0; i < n_rows; ++i) {
224                    *                        rtmp=fctp->lumped_mass_matrix[i];
225                   */                        if (ABS(rtmp)>0.) {
226                  #pragma omp parallel for schedule(static) private(i)                           rtmp3=b_n[i]/rtmp;
227                  for (i=0;i<n_rows;++i) {                        } else {
228                      u[i]+=dt2*b[i]/fctp->lumped_mass_matrix[i];                           rtmp3=fctp->u[i];
229                  }                        }
230               }                        uTilde_n[i]=rtmp3;
231               /* and the next time step */                   }
232               t+=dt2;                   omega=1.;
233               n++;                   /* no update of iteration_matrix required! */
234                 } /* end (fctp->theta > 0) */
235
236                 /* distribute uTilde_n: */
237                 Paso_Coupler_startCollect(uTilde_n_coupler,uTilde_n);
238                 Paso_Coupler_finishCollect(uTilde_n_coupler);
239                 /*
240                  * calculate QP_n[i] max_{j} (\tilde{u}[j]- \tilde{u}[i] )
241                  *           QN_n[i] min_{j} (\tilde{u}[j]- \tilde{u}[i] )
242                  *
243                  */
244                  Paso_SolverFCT_setQs(uTilde_n_coupler,QN_n,QP_n,fctp->iteration_matrix);
245                  Paso_Coupler_startCollect(QN_n_coupler,QN_n);
246                  Paso_Coupler_startCollect(QP_n_coupler,QP_n);
247                  Paso_Coupler_finishCollect(QN_n_coupler);
248                  Paso_Coupler_finishCollect(QP_n_coupler);
249                  /*
250                   * now we enter the iteration on a time-step:
251                   *
252                   */
253                   Paso_Coupler_copyAll(fctp->u_coupler, u_m_coupler);
254    /* REPLACE BY JACOBEAN FREE NEWTON */
255                   m=0;
256                   converged=FALSE;
257                   while ( (!converged) && (m<max_m) && Paso_noError()) {
258                        printf("iteration step %ld\n",m+1);
259                        /*
260                         *  set the ant diffusion fluxes:
261                         *
262                        */
263                        Paso_FCTransportProblem_setAntiDiffusionFlux(dt2,fctp,flux_matrix,u_m_coupler);
264                        /*
265                         *  apply pre flux-correction: f_{ij}:=0 if f_{ij}*(\tilde{u}[i]- \tilde{u}[j])<=0
266                         *
267                         */
268                        Paso_FCTransportProblem_applyPreAntiDiffusionCorrection(flux_matrix,uTilde_n_coupler);
269                        /*
270                         *  set flux limiters RN_m,RP_m
271                         *
272                         */
273                        Paso_FCTransportProblem_setRs(flux_matrix,fctp->lumped_mass_matrix,QN_n_coupler,QP_n_coupler,RN_m,RP_m);
274                        Paso_Coupler_startCollect(RN_m_coupler,RN_m);
275                        Paso_Coupler_startCollect(RP_m_coupler,RP_m);
276                        /*
277                         * z_m[i]=b_n[i] - (m_i*u[i] - dt2*theta*sum_{j<>i} l_{ij} (u[j]-u[i]) + dt2 q^-[i])
278                         *
279                         * note that iteration_matrix stores the negative values of the
280                         * low order transport matrix l therefore a=dt2*fctp->theta is used.
281                         */
282
283                        Paso_SolverFCT_setMuPaLuPbQ(z_m,fctp->lumped_mass_matrix, u_m_coupler,
284                                                    dt2*fctp->theta,fctp->iteration_matrix,dt2,sourceN);
285    /* for (i = 0; i < n_rows; ++i) {
286    * printf("%d: %e %e\n",i,z_m[i], b_n[i]);
287    * }
288    */
289                        #pragma omp parallel for private(i)
290                        for (i = 0; i < n_rows; ++i) z_m[i]=b_n[i]-z_m[i];
291
292                        Paso_Coupler_finishCollect(RN_m_coupler);
293                        Paso_Coupler_finishCollect(RP_m_coupler);
294                        /* add corrected fluxes into z_m */
296                        /*
297                          * now we solve the linear system to get the correction dt2:
298                          *
299                         */
300                        if (fctp->theta > 0) {
301                                /*  set the right hand side of the linear system: */
302                                options->tolerance=inner_tol;
303                                options->verbose=TRUE;
304                                Paso_solve(fctp->iteration_matrix,du_m,z_m,options);
305                                /* TODO: check errors ! */
306                          } else {
307                                #pragma omp parallel for private(i,rtmp,rtmp1)
308                                for (i = 0; i < n_rows; ++i) {
309                                    rtmp=fctp->lumped_mass_matrix[i];
310                                    if (ABS(rtmp)>0.) {
311                                       rtmp1=z_m[i]/rtmp;
312                                    } else {
313                                       rtmp1=0;
314                                    }
315                                    du_m[i]=rtmp1;
316                                }
317                          }
318                          /*
319                           * update u and calculate norm of du_m and the new u:
320                           *
321                           */
322                           norm_u=0.;
323                           norm_du=0.;
324                           #pragma omp parallel private(local_norm_u,local_norm_du)
325                           {
326                               local_norm_u=0.;
327                               local_norm_du=0.;
328                               #pragma omp for schedule(static) private(i)
329                               for (i=0;i<n_rows;++i) {
330                                    u_m[i]+=omega*du_m[i];
331                                    local_norm_u=MAX(local_norm_u,ABS(u_m[i]));
332                                    local_norm_du=MAX(local_norm_du,ABS(du_m[i]));
333                               }
334                               #pragma omp critical
335                               {
336                                   norm_u=MAX(norm_u,local_norm_u);
337                                   norm_du=MAX(norm_du,local_norm_du);
338                               }
339                           }
340                           Paso_Coupler_startCollect(u_m_coupler,u_m);
341                           #ifdef PASO_MPI
342                  double local_norm[2], norm[2];
343                              local_norm[0]=norm_u;
344                              local_norm[1]=norm_du;
345                          MPI_Allreduce(local_norm,norm, 2, MPI_DOUBLE, MPI_MAX, fctp->mpi_info->comm);
346                              norm_u=norm[0];
347                              norm_du=norm[1];
348                           #endif
349                           norm_du*=omega;
350                           converged=(norm_du <= tolerance * norm_u);
351                           m++;
352                           printf("iteration step %ld: norm u and du_m : %e %e\n",m,norm_u,norm_du);
353                           /* TODO: check if du_m has been redu_mced */
354                           Paso_Coupler_finishCollect(u_m_coupler);
355                        } /* end of inner iteration */
356                        SWAP(fctp->u,u_m,double*);
357                        SWAP(fctp->u_coupler,u_m_coupler,Paso_Coupler*);
358                        n++;
359                   } /* end of time integration */
360                   options->tolerance=tolerance;
361                   #pragma omp parallel for schedule(static) private(i)
362                   for (i=0;i<n_rows;++i) u[i]=fctp->u[i];
363          }          }
364          /*          /*
365           * save last u           *  clean-up:
366           *           *
367           */           */
368          if (Paso_noError()) {          TMPMEMFREE(b_n);
369               #pragma omp parallel for schedule(static) private(i)          Paso_SystemMatrix_free(flux_matrix);
370               for (i=0;i<n_rows;++i) {          TMPMEMFREE(sourceP);
371                   fctp->u[i]=u[i];          TMPMEMFREE(sourceN);
372               }          TMPMEMFREE(uTilde_n);
373          }          TMPMEMFREE(QN_n);
374      }          TMPMEMFREE(QP_n);
375      /*          TMPMEMFREE(RN_m);
376       *          TMPMEMFREE(RP_m);
377       * clean-up          TMPMEMFREE(z_m);
378       *          TMPMEMFREE(du_m);
379       */          TMPMEMFREE(u_m);
380      if (fctp->theta>0) {          Paso_Coupler_free(QN_n_coupler);
381              MEMFREE(b);          Paso_Coupler_free(QP_n_coupler);
382              MEMFREE(du);          Paso_Coupler_free(RN_m_coupler);
383              MEMFREE(f);          Paso_Coupler_free(RP_m_coupler);
384      }          Paso_Coupler_free(uTilde_n_coupler);
385            Paso_Coupler_free(u_m_coupler);
386  }  }

Legend:
 Removed from v.1400 changed lines Added in v.1661