1 /*     CalculiX - A 3-dimensional finite element program                 */
2 /*              Copyright (C) 1998-2021 Guido Dhondt                          */
3 
4 /*     This program is free software; you can redistribute it and/or     */
5 /*     modify it under the terms of the GNU General Public License as    */
6 /*     published by the Free Software Foundation(version 2);    */
7 /*                    */
8 
9 /*     This program is distributed in the hope that it will be useful,   */
10 /*     but WITHOUT ANY WARRANTY; without even the implied warranty of    */
11 /*     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the      */
12 /*     GNU General Public License for more details.                      */
13 
14 /*     You should have received a copy of the GNU General Public License */
15 /*     along with this program; if not, write to the Free Software       */
16 /*     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.         */
17 
18 #include <stdio.h>
19 #include <math.h>
20 #include <stdlib.h>
21 #include "CalculiX.h"
22 #ifdef SPOOLES
23    #include "spooles.h"
24 #endif
25 #ifdef SGI
26    #include "sgi.h"
27 #endif
28 #ifdef TAUCS
29    #include "tau.h"
30 #endif
31 
checkconvnet(ITG * icutb,ITG * iin,double * cam1t,double * cam1f,double * cam1p,double * cam2t,double * cam2f,double * cam2p,double * camt,double * camf,double * camp,ITG * icntrl,double * dtheta,double * ctrl,double * cam1a,double * cam2a,double * cama,double * vamt,double * vamf,double * vamp,double * vama,double * qa,double * qamt,double * qamf,double * ramt,double * ramf,double * ramp,ITG * iplausi,ITG * ichannel,ITG * iaxial)32 void checkconvnet(ITG *icutb, ITG *iin,
33 		  double *cam1t, double *cam1f, double *cam1p,
34 		  double *cam2t, double *cam2f, double *cam2p,
35 		  double *camt, double *camf, double *camp,
36 		  ITG *icntrl, double *dtheta, double *ctrl,
37                   double *cam1a,double *cam2a,double *cama,
38                   double *vamt, double *vamf, double *vamp, double *vama,
39                   double *qa, double *qamt, double *qamf,
40                   double *ramt, double *ramf, double *ramp, ITG *iplausi,
41                   ITG *ichannel,ITG *iaxial){
42 
43   ITG i0,ir,ip,ic,il,ig,ia,idivergence,iin_dyn,dyna_flag_1,dyna_flag_2;
44 
45   double c2t,c2f,c2p,c2a,c1t,c1f,c1p,a2t,a2f,a2p,a2a,a1t,a1f,a1p,qamp=1.,
46          df,dc,db,dd,ran,can,rap,ea,cae,ral;
47 
48   i0=ctrl[0];ir=ctrl[1];ip=ctrl[2];ic=ctrl[3];il=ctrl[4];ig=ctrl[5];ia=ctrl[7];
49   df=ctrl[10];dc=ctrl[11];db=ctrl[12];dd=ctrl[16];ran=ctrl[18];can=ctrl[19];
50   rap=ctrl[22];ea=ctrl[23];cae=ctrl[24];ral=ctrl[25];c1t=ctrl[32];c1f=ctrl[33];
51   c1p=ctrl[34];c2t=ctrl[35];c2f=ctrl[36];c2p=ctrl[37];c2a=ctrl[38];
52   a1t=ctrl[40];a1f=ctrl[41];a1p=ctrl[42];a2t=ctrl[43];a2f=ctrl[44],a2p=ctrl[45];
53   a2a=ctrl[46];
54 
55   /* checks for dynamic convergence
56      - to avoid oscillations the check is done after a special number
57        inn_dyn of iterations */
58 
59   iin_dyn=50;
60   if(*iin%iin_dyn==0){
61 
62   /* criteria 1: change of sign */
63      dyna_flag_1=0;
64      if(*camt**cam1t>=0 && *camt**cam2t>=0){dyna_flag_1=dyna_flag_1;}
65      else{dyna_flag_1=dyna_flag_1+1;}
66      if(*camf**cam1f>=0 && *camf**cam2f>=0){dyna_flag_1=dyna_flag_1;}
67      else{dyna_flag_1=dyna_flag_1+1;}
68      if(*camp**cam1p>=0 && *camp**cam2p>=0){dyna_flag_1=dyna_flag_1;}
69      else{dyna_flag_1=dyna_flag_1+1;}
70      if(*cama**cam1a>=0 && *cama**cam2a>=0){dyna_flag_1=dyna_flag_1;}
71      else{dyna_flag_1=dyna_flag_1+1;}
72 
73   /* criteria 2: progression check */
74      dyna_flag_2=0;
75      if(fabs(*camt)<=fabs(*cam1t) && fabs(*cam1t)<=fabs(*cam2t)){dyna_flag_2=dyna_flag_2;}
76      else{dyna_flag_2=dyna_flag_2+1;}
77      if(fabs(*camf)<=fabs(*cam1f) && fabs(*cam1f)<=fabs(*cam2f)){dyna_flag_2=dyna_flag_2;}
78      else{dyna_flag_2=dyna_flag_2+1;}
79      if(fabs(*camp)<=fabs(*cam1p) && fabs(*cam1p)<=fabs(*cam2p)){dyna_flag_2=dyna_flag_2;}
80      else{dyna_flag_2=dyna_flag_2+1;}
81      if(fabs(*cama)<=fabs(*cam1a) && fabs(*cam1a)<=fabs(*cam2a)){dyna_flag_2=dyna_flag_2;}
82      else{dyna_flag_2=dyna_flag_2+1;}
83 
84   }
85 
86 
87 /* Das wird aus meiner Sicht nicht mehr benoetigt
88   if(*cam1t<*cam2t) {*cam2t=*cam1t;}
89   if(*cam1f<*cam2f) {*cam2f=*cam1f;}
90   if(*cam1p<*cam2p) {*cam2p=*cam1p;}
91   if(*cam1a<*cam2a) {*cam2a=*cam1a;}
92   */
93 
94 
95   /* check for convergence or divergence;
96      the convergence check consists of
97      - a comparison of the correction in
98        the latest network iteration with the change since the
99        start of the network calculations
100      - a comparison of the residual in the latest network
101        iteration with mean typical values of the equation terms */
102 
103   if(*ichannel==1){*ramt=0.;*ramf=0.;*ramp=0.;}
104 
105   if((fabs(*camt)<=c2t**vamt)&&(*ramt<c1t**qamt)&&(fabs(*camt)<=a2t)&&
106      (*ramt<a1t/(*iaxial))&&(fabs(*camf)<=c2f**vamf)&&(*ramf<c1f**qamf)&&
107      (fabs(*camf)<=a2f/(*iaxial))&&(*ramf<a1f/(*iaxial))&&
108      (fabs(*camp)<=c2p**vamp)&&(*ramp<c1p*qamp)&&(fabs(*camp)<a2p)&&(*ramp<a1p)&&
109      (fabs(*cama)<=c2a**vama)&&(fabs(*cama)<=a2a)&&(*iplausi==1)&&
110      (*iin>3)){
111 
112       /* increment convergence reached */
113 
114       printf("      flow network: convergence in gas iteration %" ITGFORMAT " \n\n",*iin);
115       *icntrl=1;
116       *icutb=0;
117   }
118 
119   else {
120 
121       idivergence=0;
122 
123       /* divergence based on temperatures */
124 
125       if((*iin>=20*i0)||(fabs(*camt)>1.e20)){
126 	  if((fabs(*cam1t)>=fabs(*cam2t))&&(fabs(*camt)>=fabs(*cam2t))&&(fabs(*camt)>c2t**vamt)){
127 	      idivergence=1;
128 	  }
129       }
130 
131       /* divergence based on the mass flux */
132 
133       if((*iin>=20*i0)||(fabs(*camf)>1.e20)){
134 	  if((fabs(*cam1f)>=fabs(*cam2f))&&(fabs(*camf)>=fabs(*cam2f))&&(fabs(*camf)>c2f**vamf)){
135 	      idivergence=1;
136 	  }
137       }
138 
139       /* divergence based on pressures */
140 
141       if((*iin>=20*i0)||(fabs(*camp)>1.e20)){
142 	  if((fabs(*cam1p)>=fabs(*cam2p))&&(fabs(*camp)>=fabs(*cam2p))&&(fabs(*camp)>c2p**vamp)){
143 	      idivergence=1;
144 	  }
145       }
146 
147       /* divergence based on geometry */
148 
149       if((*iin>=20*i0)||(fabs(*cama)>1.e20)){
150 	  if((fabs(*cam1a)>=fabs(*cam2a))&&(fabs(*cama)>=fabs(*cam2a))&&(fabs(*cama)>c2a**vama)){
151 	      idivergence=1;
152 	  }
153       }
154 
155       /* divergence based on the number of iterations */
156 
157       if(*iin>20*ic) idivergence=1;
158 
159       /* divergence based on singular matrix or negative pressures */
160 
161       if(*iin==0) idivergence=1;
162 
163       if(idivergence==1){
164 	  *dtheta=*dtheta*df;
165 	  printf("\n network divergence; the under-relaxation parameter is decreased to %e\n",*dtheta);
166 	  printf(" the network iteration for the increment is reattempted\n\n");
167 	  *iin=0;
168 	  (*icutb)++;
169 	  if(*icutb>ia){
170 	      qa[2]=0.25;
171 	      *icntrl=1;
172 //	    printf("\n *ERROR: too many cutbacks\n");
173 //	    FORTRAN(stop,());
174 	  }
175       }else{
176 	  if(*iin%iin_dyn==0){
177 	     if(dyna_flag_1==0 && dyna_flag_2==0 && *iplausi==1){
178 		printf("      good convergence --> *dtheta is increased %" ITGFORMAT "\n",*iin);
179 		*dtheta=*dtheta*(1.2);
180 		if(*dtheta>=1){
181 	           *dtheta=1.;
182 		}
183 	     }
184 	     else if(dyna_flag_1!=0 && dyna_flag_2!=0 && *iplausi!=1){
185 		printf("      bad convergence progression --> *dtheta is decreased %" ITGFORMAT "\n",*iin);
186 		*dtheta=*dtheta*(0.8);
187 	     }
188 	     else{
189 	        printf("      no convergence\n\n");
190 	     }
191 	  }
192 	  else{
193 	     printf("      no convergence\n\n");
194 	  }
195       }
196   }
197   return;
198 }
199