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

Annotation of /trunk/paso/src/FCTSolver.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2987 - (hide annotations)
Tue Mar 16 01:32:43 2010 UTC (10 years ago) by gross
File MIME type: text/plain
File size: 13397 byte(s)
FCT solver rewritten
1 gross 2987
2     /*******************************************************
3     *
4     * Copyright (c) 2003-2010 by University of Queensland
5     * Earth Systems Science Computational Center (ESSCC)
6     * http://www.uq.edu.au/esscc
7     *
8     * Primary Business: Queensland, Australia
9     * Licensed under the Open Software License version 3.0
10     * http://www.opensource.org/licenses/osl-3.0.php
11     *
12     *******************************************************/
13    
14    
15     /**************************************************************/
16    
17     /* Paso: Transport solver with flux corretion (L is row sum zero)
18     *
19     * - Mv_t=Lv v(0)=u
20     *
21     * to return v(dt)
22     *
23     */
24     /**************************************************************/
25    
26     /* Author: l.gross@uq.edu.au */
27    
28     /**************************************************************/
29    
30     #include "FCTSolver.h"
31     #include "Solver.h"
32     #include "PasoUtil.h"
33    
34     Paso_Function* Paso_FCTSolver_Function_alloc(Paso_TransportProblem *fctp, Paso_Options* options)
35     {
36     const dim_t n=Paso_SystemMatrix_getTotalNumRows(fctp->transport_matrix);
37     const dim_t blockSize=Paso_TransportProblem_getBlockSize(fctp);
38     Paso_Function * out=NULL;
39     Paso_FCTSolver *more=NULL;
40     out=MEMALLOC(1,Paso_Function);
41     if (! Paso_checkPtr(out)) {
42     out->kind=FCT;
43     out->mpi_info=Paso_MPIInfo_getReference(fctp->mpi_info);
44     out->n=n;
45     out->b=TMPMEMALLOC(n,double); /*b_m */
46     Paso_checkPtr(out->b);
47     out->tmp=TMPMEMALLOC(n,double); /* z_m */
48     Paso_checkPtr(out->tmp);
49    
50     more=MEMALLOC(1,Paso_FCTSolver);
51     out->more=(void*) more;
52     if (! Paso_checkPtr(more)) {
53     more->transportproblem=Paso_TransportProblem_getReference(fctp);
54     more->uTilde_n=TMPMEMALLOC(n,double);
55     Paso_checkPtr(more->uTilde_n);
56     more->QN_n=TMPMEMALLOC(n,double);
57     Paso_checkPtr(more->QN_n);
58     more->QP_n=TMPMEMALLOC(n,double);
59     Paso_checkPtr(more->QP_n);
60     more->RN_m=TMPMEMALLOC(n,double);
61     Paso_checkPtr(more->RN_m);
62     more->RP_m=TMPMEMALLOC(n,double);
63     Paso_checkPtr(more->RP_m);
64     more->QN_n_coupler=Paso_Coupler_alloc(Paso_TransportProblem_borrowConnector(fctp),blockSize);
65     more->QP_n_coupler=Paso_Coupler_alloc(Paso_TransportProblem_borrowConnector(fctp),blockSize);
66     more->RN_m_coupler=Paso_Coupler_alloc(Paso_TransportProblem_borrowConnector(fctp),blockSize);
67     more->RP_m_coupler=Paso_Coupler_alloc(Paso_TransportProblem_borrowConnector(fctp),blockSize);
68     more->uTilde_n_coupler=Paso_Coupler_alloc(Paso_TransportProblem_borrowConnector(fctp),blockSize);
69     more->u_m_coupler=Paso_Coupler_alloc(Paso_TransportProblem_borrowConnector(fctp),blockSize);
70     more->flux_matrix_m=Paso_SystemMatrix_alloc(fctp->transport_matrix->type,
71     fctp->transport_matrix->pattern,
72     fctp->transport_matrix->row_block_size,
73     fctp->transport_matrix->col_block_size, TRUE);
74    
75     }
76     Paso_Solver_setPreconditioner(fctp->iteration_matrix,options);
77     }
78     if (Paso_noError()) {
79     return out;
80     } else {
81     Paso_FCTSolver_Function_free(out);
82     return NULL;
83     }
84     }
85    
86     void Paso_FCTSolver_Function_free(Paso_Function * in)
87     {
88     Paso_FCTSolver *more=NULL;
89     if (in!=NULL) {
90     Paso_MPIInfo_free(in->mpi_info);
91     MEMFREE(in->tmp);
92     MEMFREE(in->b);
93     more=(Paso_FCTSolver *) (in->more);
94     if (NULL !=more) {
95     Paso_TransportProblem_free(more->transportproblem);
96     Paso_SystemMatrix_free(more->flux_matrix_m);
97     TMPMEMFREE(more->uTilde_n);
98     TMPMEMFREE(more->QN_n);
99     TMPMEMFREE(more->QP_n);
100     TMPMEMFREE(more->RN_m);
101     TMPMEMFREE(more->RP_m);
102     Paso_Coupler_free(more->QN_n_coupler);
103     Paso_Coupler_free(more->QP_n_coupler);
104     Paso_Coupler_free(more->RN_m_coupler);
105     Paso_Coupler_free(more->RP_m_coupler);
106     Paso_Coupler_free(more->uTilde_n_coupler);
107     Paso_Coupler_free(more->u_m_coupler);
108     }
109     MEMFREE(in);
110     }
111     }
112     double Paso_FCTSolver_getSafeTimeStepSize(Paso_TransportProblem* fctp)
113     {
114     dim_t i, n;
115     double dt_max=LARGE_POSITIVE_FLOAT, dt_max_loc;
116     register double l_ii,m;
117     n=Paso_SystemMatrix_getTotalNumRows(fctp->transport_matrix);
118     /* extract the row sum of the advective part */
119     Paso_SystemMatrix_rowSum(fctp->mass_matrix,fctp->lumped_mass_matrix);
120    
121     /* set low order transport operator */
122     Paso_FCTSolver_setLowOrderOperator(fctp);
123    
124     if (Paso_noError()) {
125     /*
126     * calculate time step size:
127     */
128     dt_max=LARGE_POSITIVE_FLOAT;
129     #pragma omp parallel private(dt_max_loc)
130     {
131     dt_max_loc=LARGE_POSITIVE_FLOAT;
132     #pragma omp for schedule(static) private(i,l_ii,m)
133     for (i=0;i<n;++i) {
134     l_ii=fctp->main_diagonal_low_order_transport_matrix[i];
135     m=fctp->lumped_mass_matrix[i];
136     if ( (l_ii<0 && m>0.) || (l_ii>0 && m<0) ) {
137     dt_max_loc=MIN(dt_max_loc,-m/l_ii);
138     }
139     }
140     #pragma omp critical
141     {
142     dt_max=MIN(dt_max,dt_max_loc);
143     }
144     }
145     #ifdef PASO_MPI
146     dt_max_loc = dt_max;
147     MPI_Allreduce(&dt_max_loc, &dt_max, 1, MPI_DOUBLE, MPI_MIN, fctp->mpi_info->comm);
148     #endif
149     if (dt_max<LARGE_POSITIVE_FLOAT) dt_max*=fctp->dt_factor;
150     }
151     return dt_max;
152     }
153     /*
154     * evaluates F as
155     * (m_i*omega - l_ij)*(F_j/omega)
156     * =(m u^n[i] + dt*(1-theta) sum_{j <> i} l_{ij}*(u^n[j]-u^n[i]))-(m_i*u[i] - dt*theta*sum_{j<>i} l_{ij} (u[j]-u[i]) )- antidiffusion
157     *
158     */
159     err_t Paso_FCTSolver_Function_call(Paso_Function * F,double* value, const double* arg, Paso_Performance *pp)
160     {
161     Paso_FCTSolver *more=(Paso_FCTSolver *) (F->more);
162    
163    
164     /* set z_m in tmp */
165     Paso_FCTSolver_setUpRightHandSide(more->transportproblem,more->dt,arg,more->u_m_coupler,F->tmp,more->flux_matrix_m,
166     more->uTilde_n_coupler,F->b,
167     more->QN_n_coupler,more->QP_n_coupler,more->RN_m,
168     more->RN_m_coupler,more->RP_m,more->RP_m_coupler,pp);
169     /* apply preconditoner do get du = */
170     Paso_Solver_solvePreconditioner(more->transportproblem->iteration_matrix,value,F->tmp);
171     return NO_ERROR;
172     }
173    
174     err_t Paso_FCTSolver_solve(Paso_Function* F, double* u, double dt, Paso_Options* options, Paso_Performance *pp)
175     {
176     double norm_u_tilde, ATOL, norm_u, norm_du, *du=NULL;
177     err_t errorCode=SOLVER_NO_ERROR;
178     Paso_FCTSolver *more=(Paso_FCTSolver *) (F->more);
179     const double omega=1./dt*( more->transportproblem->useBackwardEuler ? 1. : 2.);
180     Paso_TransportProblem* fctp=more->transportproblem;
181     const dim_t n=Paso_SystemMatrix_getTotalNumRows(fctp->transport_matrix);
182     const double atol=options->absolute_tolerance;
183     const double rtol=options->tolerance;
184     const dim_t max_m=options->iter_max;
185     dim_t m=0;
186     bool_t converged=FALSE, max_m_reached=FALSE;
187    
188     /* tolerance? */
189     more->dt=dt;
190     Paso_FCTSolver_setUp(fctp,dt,u, F->b,more->uTilde_n,more->uTilde_n_coupler,more->QN_n,more->QN_n_coupler,more->QP_n,more->QP_n_coupler,
191     options,pp);
192    
193    
194     norm_u_tilde=Paso_lsup(n,more->uTilde_n,F->mpi_info);
195     ATOL= rtol * norm_u_tilde + atol ;
196     if (options->verbose) printf("Paso_FCTSolver_solve: iteration starts u_tilda lsup = %e (abs. tol = %e)\n",norm_u_tilde,ATOL);
197     if (more->transportproblem->useBackwardEuler && FALSE) {
198     options->absolute_tolerance = ATOL/omega;
199     options->tolerance=0;
200     errorCode=Paso_Solver_NewtonGMRES(F,u,options,pp);
201     options->absolute_tolerance=atol;
202     options->tolerance=rtol;
203     } else {
204     m=0;
205     converged=FALSE;
206     max_m_reached=FALSE;
207     du=MEMALLOC(n,double);
208     if (Paso_checkPtr(du)) {
209     errorCode=SOLVER_MEMORY_ERROR;
210     } else {
211     /* tolerance? */
212    
213     while ( (!converged) && (! max_m_reached) && Paso_noError()) {
214     errorCode=Paso_FCTSolver_Function_call(F,du, u, pp);
215     Paso_Update(n,1.,u,omega,du);
216     norm_u=Paso_lsup(n,u, fctp->mpi_info);
217     norm_du=Paso_lsup(n,du, fctp->mpi_info);
218     if (options->verbose) printf("Paso_FCTSolver_solve: step %d: increment= %e (tolerance = %e)\n",m+1, norm_du*omega, ATOL);
219     max_m_reached=(m>max_m);
220     converged=(norm_du*omega <= ATOL) ;
221     m++;
222     }
223     }
224     MEMFREE(du);
225     if (errorCode == SOLVER_NO_ERROR) {
226     if (converged) {
227     if (options->verbose) printf("Paso_FCTSolver_solve: iteration is completed.\n");
228     errorCode=SOLVER_NO_ERROR;
229     } else if (max_m_reached) {
230     errorCode=SOLVER_MAXITER_REACHED;
231     }
232     }
233     }
234     return errorCode;
235     }
236    
237    
238    
239     err_t Paso_FCTSolver_setUpRightHandSide(Paso_TransportProblem* fctp, const double dt, const double *u_m,
240     Paso_Coupler* u_m_coupler, double * z_m,
241     Paso_SystemMatrix* flux_matrix, Paso_Coupler* uTilde_coupler, const double *b,
242     Paso_Coupler* QN_coupler, Paso_Coupler* QP_coupler,
243     double *RN_m, Paso_Coupler* RN_m_coupler, double* RP_m, Paso_Coupler* RP_m_coupler,
244     Paso_Performance* pp)
245     {
246     const double omega=1./dt* (fctp->useBackwardEuler ? 1. : 2.);
247     const dim_t n=Paso_SystemMatrix_getTotalNumRows(fctp->transport_matrix);
248     /* distribute u */
249     Paso_Coupler_startCollect(u_m_coupler,u_m);
250     Paso_Coupler_finishCollect(u_m_coupler);
251     /*
252     * set the ant diffusion fluxes:
253     *
254     */
255     Paso_FCTSolver_setAntiDiffusionFlux(dt,fctp,flux_matrix,u_m_coupler);
256     /*
257     * apply pre flux-correction: f_{ij}:=0 if f_{ij}*(\tilde{u}[i]- \tilde{u}[j])<=0
258     *
259     */
260     Paso_FCTSolver_applyPreAntiDiffusionCorrection(flux_matrix,uTilde_coupler);
261     /*
262     * set flux limiters RN_m,RP_m
263     *
264     */
265     Paso_FCTSolver_setRs(flux_matrix,fctp->lumped_mass_matrix,QN_coupler,QP_coupler,RN_m,RP_m);
266     Paso_Coupler_startCollect(RN_m_coupler,RN_m);
267     Paso_Coupler_startCollect(RP_m_coupler,RP_m);
268     /*
269     * z_m[i]=b[i] - (m_i*u_m[i] - dt*theta*sum_{j<>i} l_{ij} (u_m[j]-u_m[i]) )
270     *
271     * note that iteration_matrix stores the negative values of the
272     * low order transport matrix l therefore a=dt*theta is used.
273     */
274     Paso_FCTSolver_setMuPaLu(z_m,fctp->lumped_mass_matrix, u_m_coupler,1./omega,fctp->iteration_matrix);
275     /*{
276     int kk;
277     for (kk=0;kk<n;kk++) printf("z_m %d : %e %e -> %e\n",kk,z_m[kk], b[kk],z_m[kk]-b[kk]);
278     }
279     */
280     /* z_m=b-z_m */
281     Paso_Update(n,-1.,z_m,1.,b);
282    
283     Paso_Coupler_finishCollect(RN_m_coupler);
284     Paso_Coupler_finishCollect(RP_m_coupler);
285     /* add corrected fluxes into z_m */
286     Paso_FCTSolver_addCorrectedFluxes(z_m,flux_matrix,RN_m_coupler,RP_m_coupler);
287     return SOLVER_NO_ERROR;
288     }
289    
290     void Paso_FCTSolver_setUp(Paso_TransportProblem* fctp, const double dt, const double *u, double* b, double* uTilde,
291     Paso_Coupler* uTilde_coupler, double *QN, Paso_Coupler* QN_coupler, double *QP, Paso_Coupler* QP_coupler,
292     Paso_Options* options, Paso_Performance* pp)
293     {
294     dim_t i;
295     const dim_t n=Paso_SystemMatrix_getTotalNumRows(fctp->transport_matrix);
296     const double omega=1./dt* (fctp->useBackwardEuler ? 1. : 2.);
297     register double m, u_tilde_i, rtmp4;
298     /* distribute u */
299     Paso_Coupler_startCollect(fctp->u_coupler,u);
300     Paso_Coupler_finishCollect(fctp->u_coupler);
301     /*
302     * b^n[i]=m u^n[i] + dt*(1-theta) sum_{j <> i} l_{ij}*(u^n[j]-u^n[i])
303     *
304     * note that iteration_matrix stores the negative values of the
305     * low order transport matrix l therefore a=-dt*(1-fctp->theta) is used.
306     *
307     */
308     if (fctp->useBackwardEuler) {
309     Paso_FCTSolver_setMuPaLu(b,fctp->lumped_mass_matrix,fctp->u_coupler,0.,fctp->iteration_matrix);
310     } else {
311     Paso_FCTSolver_setMuPaLu(b,fctp->lumped_mass_matrix,fctp->u_coupler,-dt*0.5,fctp->iteration_matrix);
312     }
313     /*
314     * uTilde[i]=b[i]/m[i]
315     *
316     * fctp->iteration_matrix[i,i]=m[i]/(dt theta) -l[i,i]
317     *
318     */
319    
320     Paso_solve_free(fctp->iteration_matrix);
321     #pragma omp parallel for private(i,m,u_tilde_i,rtmp4)
322     for (i = 0; i < n; ++i) {
323     m=fctp->lumped_mass_matrix[i];
324     u_tilde_i=b[i]/m;
325     rtmp4=m*omega-fctp->main_diagonal_low_order_transport_matrix[i];
326     fctp->iteration_matrix->mainBlock->val[fctp->main_iptr[i]]=rtmp4;
327     uTilde[i]=u_tilde_i;
328     /* printf("uTilde %d %e and %e : %e : %e %e\n",i,u_tilde_i, b[i], rtmp4, m, fctp->main_diagonal_low_order_transport_matrix[i]); */
329     }
330     Performance_startMonitor(pp,PERFORMANCE_PRECONDITIONER_INIT);
331     Paso_Solver_setPreconditioner(fctp->iteration_matrix,options);
332     Performance_stopMonitor(pp,PERFORMANCE_PRECONDITIONER_INIT);
333    
334     /* distribute uTilde: */
335     Paso_Coupler_startCollect(uTilde_coupler,uTilde);
336     Paso_Coupler_finishCollect(uTilde_coupler);
337     /*
338     * calculate QP[i] max_{j} (\tilde{u}[j]- \tilde{u}[i] )
339     * QN[i] min_{j} (\tilde{u}[j]- \tilde{u}[i] )
340     *
341     */
342     Paso_FCTSolver_setQs(uTilde_coupler,QN,QP,fctp->iteration_matrix);
343     Paso_Coupler_startCollect(QN_coupler,QN);
344     Paso_Coupler_startCollect(QP_coupler,QP);
345     Paso_Coupler_finishCollect(QN_coupler);
346     Paso_Coupler_finishCollect(QP_coupler);
347     }

  ViewVC Help
Powered by ViewVC 1.1.26