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 <unistd.h>
19 #include <stdio.h>
20 #include <math.h>
21 #include <stdlib.h>
22 #include <pthread.h>
23 #include "CalculiX.h"
24 
25 static char *lakon1,*matname1,*sideload1;
26 
27 static ITG *kon1,*ipkon1,*ne1,*nelcon1,*nrhcon1,*nalcon1,*ielmat1,*ielorien1,
28     *norien1,*ntmat1_,*ithermal1,*iperturb1,*iout1,*nmethod1,
29     *nplkcon1,*npmat1_,*mi1,*ncmat1_,*nstate1_,*ielprop1,*inoel1,
30     *istep1,*iinc1,calcul_fn1,calcul_qa1,*nplicon1,*iponoel1,
31     *nal=NULL,*ipompc1,*nodempc1,*nmpc1,*ncocon1,*ikmpc1,*ilmpc1,
32     num_cpus,mt1,*nk1,*nshcon1,*nelemload1,*nload1,mortar1,
33     *istartset1,*iendset1,*ialset1,*iactive1,*network1,*ipobody1,*ibody1,
34     *neapar=NULL,*nebpar=NULL;
35 
36 static double *co1,*v1,*elcon1,*rhcon1,*alcon1,*orab1,*t01,*eei1,
37     *fn1=NULL,*qa1=NULL,*vold1,*dtime1,*time1,*prop1,
38     *ttime1,*plkcon1,*xstateini1,*xstiff1,*xstate1,*sti1,
39     *springarea1,*reltime1,*coefmpc1,*vini1,
40     *cocon1,*qfx1,*shcon1,*xload1,*plicon1,
41     *xloadold1,*h01,*pslavsurf1,*pmastsurf1,*clearini1,*xbody1;
42 
resultsinduction(double * co,ITG * nk,ITG * kon,ITG * ipkon,char * lakon,ITG * ne,double * v,double * stn,ITG * inum,double * elcon,ITG * nelcon,double * rhcon,ITG * nrhcon,double * alcon,ITG * nalcon,double * alzero,ITG * ielmat,ITG * ielorien,ITG * norien,double * orab,ITG * ntmat_,double * t0,double * t1,ITG * ithermal,double * prestr,ITG * iprestr,char * filab,double * eme,double * emn,double * een,ITG * iperturb,double * f,double * fn,ITG * nactdof,ITG * iout,double * qa,double * vold,double * b,ITG * nodeboun,ITG * ndirboun,double * xboun,ITG * nboun,ITG * ipompc,ITG * nodempc,double * coefmpc,char * labmpc,ITG * nmpc,ITG * nmethod,double * cam,ITG * neq,double * veold,double * accold,double * bet,double * gam,double * dtime,double * time,double * ttime,double * plicon,ITG * nplicon,double * plkcon,ITG * nplkcon,double * xstateini,double * xstiff,double * xstate,ITG * npmat_,double * epn,char * matname,ITG * mi,ITG * ielas,ITG * icmd,ITG * ncmat_,ITG * nstate_,double * sti,double * vini,ITG * ikboun,ITG * ilboun,double * ener,double * enern,double * emeini,double * xstaten,double * eei,double * enerini,double * cocon,ITG * ncocon,char * set,ITG * nset,ITG * istartset,ITG * iendset,ITG * ialset,ITG * nprint,char * prlab,char * prset,double * qfx,double * qfn,double * trab,ITG * inotr,ITG * ntrans,double * fmpc,ITG * nelemload,ITG * nload,ITG * ikmpc,ITG * ilmpc,ITG * istep,ITG * iinc,double * springarea,double * reltime,ITG * ne0,double * xforc,ITG * nforc,double * thicke,double * shcon,ITG * nshcon,char * sideload,double * xload,double * xloadold,ITG * icfd,ITG * inomat,double * h0,ITG * islavnode,ITG * nslavnode,ITG * ntie,ITG * ielprop,double * prop,ITG * iactive,double * energyini,double * energy,ITG * iponoel,ITG * inoel,char * orname,ITG * network,ITG * ipobody,double * xbody,ITG * ibody,ITG * nbody)43 void resultsinduction(double *co,ITG *nk,ITG *kon,ITG *ipkon,char *lakon,
44        ITG *ne,
45        double *v,double *stn,ITG *inum,double *elcon,ITG *nelcon,
46        double *rhcon,ITG *nrhcon,double *alcon,ITG *nalcon,double *alzero,
47        ITG *ielmat,ITG *ielorien,ITG *norien,double *orab,ITG *ntmat_,
48        double *t0,
49        double *t1,ITG *ithermal,double *prestr,ITG *iprestr,char *filab,
50        double *eme,double *emn,
51        double *een,ITG *iperturb,double *f,double *fn,ITG *nactdof,ITG *iout,
52        double *qa,double *vold,double *b,ITG *nodeboun,ITG *ndirboun,
53        double *xboun,ITG *nboun,ITG *ipompc,ITG *nodempc,double *coefmpc,
54        char *labmpc,ITG *nmpc,ITG *nmethod,double *cam,ITG *neq,double *veold,
55        double *accold,double *bet,double *gam,double *dtime,double *time,
56        double *ttime,double *plicon,ITG *nplicon,double *plkcon,
57        ITG *nplkcon,double *xstateini,double *xstiff,double *xstate,ITG *npmat_,
58        double *epn,char *matname,ITG *mi,ITG *ielas,ITG *icmd,ITG *ncmat_,
59        ITG *nstate_,
60        double *sti,double *vini,ITG *ikboun,ITG *ilboun,double *ener,
61        double *enern,double *emeini,double *xstaten,double *eei,double *enerini,
62        double *cocon,ITG *ncocon,char *set,ITG *nset,ITG *istartset,
63        ITG *iendset,
64        ITG *ialset,ITG *nprint,char *prlab,char *prset,double *qfx,double *qfn,
65        double *trab,
66        ITG *inotr,ITG *ntrans,double *fmpc,ITG *nelemload,ITG *nload,
67        ITG *ikmpc,ITG *ilmpc,
68        ITG *istep,ITG *iinc,double *springarea,double *reltime, ITG *ne0,
69        double *xforc, ITG *nforc, double *thicke,
70        double *shcon,ITG *nshcon,char *sideload,double *xload,
71        double *xloadold,ITG *icfd,ITG *inomat,double *h0,ITG *islavnode,
72        ITG *nslavnode,ITG *ntie,ITG *ielprop,double *prop,ITG *iactive,
73        double *energyini,double *energy,ITG *iponoel,ITG *inoel,char *orname,
74        ITG *network,ITG *ipobody,double *xbody,ITG *ibody,ITG *nbody){
75 
76     /* variables for multithreading procedure */
77 
78   char *env,*envloc,*envsys,*tieset=NULL;
79 
80     ITG intpointvarm,calcul_fn,calcul_f,calcul_qa,calcul_cauchy,nener,ikin,
81         intpointvart,mt=mi[1]+1,i,j,*ithread=NULL,*islavsurf=NULL,
82       sys_cpus,mortar=0,*islavact=NULL,*itiefac=NULL;
83 
84     double *pmastsurf=NULL,*clearini=NULL,*pslavsurf=NULL,*cdn=NULL;
85 
86     /*
87 
88      calculating integration point values (strains, stresses,
89      heat fluxes, material tangent matrices and nodal forces)
90 
91      storing the nodal and integration point results in the
92      .dat file
93 
94      iout=-2: v is assumed to be known and is used to
95               calculate strains, stresses..., no result output
96               corresponds to iout=-1 with in addition the
97               calculation of the internal energy density
98      iout=-1: v is assumed to be known and is used to
99               calculate strains, stresses..., no result output;
100               is used to take changes in SPC's and MPC's at the
101               start of a new increment or iteration into account
102      iout=0: v is calculated from the system solution
103              and strains, stresses.. are calculated, no result output
104      iout=1:  v is calculated from the system solution and strains,
105               stresses.. are calculated, requested results output
106      iout=2: v is assumed to be known and is used to
107              calculate strains, stresses..., requested results output */
108 
109     num_cpus=0;
110     sys_cpus=0;
111 
112     /* explicit user declaration prevails */
113 
114     envsys=getenv("NUMBER_OF_CPUS");
115     if(envsys){
116 	sys_cpus=atoi(envsys);
117 	if(sys_cpus<0) sys_cpus=0;
118     }
119 
120     /* automatic detection of available number of processors */
121 
122     if(sys_cpus==0){
123 	sys_cpus = getSystemCPUs();
124 	if(sys_cpus<1) sys_cpus=1;
125     }
126 
127     /* local declaration prevails, if strictly positive */
128 
129     envloc = getenv("CCX_NPROC_RESULTS");
130     if(envloc){
131 	num_cpus=atoi(envloc);
132 	if(num_cpus<0){
133 	    num_cpus=0;
134 	}else if(num_cpus>sys_cpus){
135 	    num_cpus=sys_cpus;
136 	}
137 
138     }
139 
140     /* else global declaration, if any, applies */
141 
142     env = getenv("OMP_NUM_THREADS");
143     if(num_cpus==0){
144 	if (env)
145 	    num_cpus = atoi(env);
146 	if (num_cpus < 1) {
147 	    num_cpus=1;
148 	}else if(num_cpus>sys_cpus){
149 	    num_cpus=sys_cpus;
150 	}
151     }
152 
153 // next line is to be inserted in a similar way for all other paralell parts
154 
155     if(*ne<num_cpus) num_cpus=*ne;
156 
157     pthread_t tid[num_cpus];
158 
159     /* 1. nodewise storage of the primary variables
160        2. determination which derived variables have to be calculated */
161 
162     FORTRAN(resultsini_em,(nk,v,ithermal,filab,iperturb,f,fn,
163        nactdof,iout,qa,b,nodeboun,ndirboun,
164        xboun,nboun,ipompc,nodempc,coefmpc,labmpc,nmpc,nmethod,cam,neq,
165        veold,dtime,mi,vini,nprint,prlab,
166        &intpointvarm,&calcul_fn,&calcul_f,&calcul_qa,&calcul_cauchy,&nener,
167        &ikin,&intpointvart,xforc,nforc));
168 
169     /* electromagnetic calculation is linear: should not be taken
170        into account in the convergence check (only thermal part
171        is taken into account) */
172 
173     cam[0]=0.;
174 
175     /* next statement allows for storing the displacements in each
176       iteration: for debugging purposes */
177 
178     if((strcmp1(&filab[3],"I")==0)&&(*iout==0)){
179 	FORTRAN(frditeration,(co,nk,kon,ipkon,lakon,ne,v,
180 		ttime,ielmat,matname,mi,istep,iinc,ithermal));
181     }
182 
183     /* calculating the stresses and material tangent at the
184        integration points; calculating the internal forces */
185 
186     if(((ithermal[0]<=1)||(ithermal[0]>=3))&&(intpointvarm==1)){
187 
188         /* determining the element bounds in each thread */
189 
190 	NNEW(neapar,ITG,num_cpus);
191 	NNEW(nebpar,ITG,num_cpus);
192 	elementcpuload(neapar,nebpar,ne,ipkon,&num_cpus);
193 
194 	co1=co;kon1=kon;ipkon1=ipkon;lakon1=lakon;v1=v;elcon1=elcon;
195         nelcon1=nelcon;ielmat1=ielmat;ntmat1_=ntmat_;vini1=vini;dtime1=dtime;
196         matname1=matname;mi1=mi;ncmat1_=ncmat_;sti1=sti;alcon1=alcon;
197 	nalcon1=nalcon;h01=h0;ne1=ne;istartset1=istartset;iendset1=iendset;
198         ialset1=ialset;iactive1=iactive;fn1=fn;eei1=eei;iout1=iout;
199 	nmethod1=nmethod;
200 
201 	/* calculating the magnetic field */
202 
203 	if(((*nmethod!=4)&&(*nmethod!=5))||(iperturb[0]>1)){
204 		printf(" Using up to %" ITGFORMAT " cpu(s) for the magnetic field calculation.\n\n", num_cpus);
205 	}
206 
207 	/* create threads and wait */
208 
209 	NNEW(ithread,ITG,num_cpus);
210 	for(i=0; i<num_cpus; i++)  {
211 	    ithread[i]=i;
212 	    pthread_create(&tid[i], NULL, (void *)resultsemmt, (void *)&ithread[i]);
213 	}
214 	for(i=0; i<num_cpus; i++)  pthread_join(tid[i], NULL);
215 	SFREE(ithread);SFREE(neapar);SFREE(nebpar);
216 
217 	qa[0]=0.;
218     }
219 
220     /* calculating the thermal flux and material tangent at the
221        integration points; calculating the internal point flux */
222 
223     if((ithermal[0]>=2)&&(intpointvart==1)){
224 
225         /* determining the element bounds in each thread */
226 
227 	NNEW(neapar,ITG,num_cpus);
228 	NNEW(nebpar,ITG,num_cpus);
229 	elementcpuload(neapar,nebpar,ne,ipkon,&num_cpus);
230 
231 	NNEW(fn1,double,num_cpus*mt**nk);
232 	NNEW(qa1,double,num_cpus*4);
233 	NNEW(nal,ITG,num_cpus);
234 
235 	co1=co;kon1=kon;ipkon1=ipkon;lakon1=lakon;v1=v;
236         elcon1=elcon;nelcon1=nelcon;rhcon1=rhcon;nrhcon1=nrhcon;
237 	ielmat1=ielmat;ielorien1=ielorien;norien1=norien;orab1=orab;
238         ntmat1_=ntmat_;t01=t0;iperturb1=iperturb;iout1=iout;vold1=vold;
239         ipompc1=ipompc;nodempc1=nodempc;coefmpc1=coefmpc;nmpc1=nmpc;
240         dtime1=dtime;time1=time;ttime1=ttime;plkcon1=plkcon;
241         nplkcon1=nplkcon;xstateini1=xstateini;xstiff1=xstiff;
242         xstate1=xstate;npmat1_=npmat_;matname1=matname;mi1=mi;
243         ncmat1_=ncmat_;nstate1_=nstate_;cocon1=cocon;ncocon1=ncocon;
244         qfx1=qfx;ikmpc1=ikmpc;ilmpc1=ilmpc;istep1=istep;iinc1=iinc;
245         springarea1=springarea;calcul_fn1=calcul_fn;calcul_qa1=calcul_qa;
246         mt1=mt;nk1=nk;shcon1=shcon;nshcon1=nshcon;ithermal1=ithermal;
247         nelemload1=nelemload;nload1=nload;nmethod1=nmethod;reltime1=reltime;
248         sideload1=sideload;xload1=xload;xloadold1=xloadold;
249         pslavsurf1=pslavsurf;pmastsurf1=pmastsurf;mortar1=mortar;
250         clearini1=clearini;plicon1=plicon;nplicon1=nplicon;ielprop1=ielprop;
251         prop1=prop;iponoel1=iponoel;inoel1=inoel;network1=network;
252         ipobody1=ipobody;ibody1=ibody;xbody1=xbody;
253 
254 	/* calculating the heat flux */
255 
256 	printf(" Using up to %" ITGFORMAT " cpu(s) for the heat flux calculation.\n\n", num_cpus);
257 
258 	/* create threads and wait */
259 
260 	NNEW(ithread,ITG,num_cpus);
261 	for(i=0; i<num_cpus; i++)  {
262 	    ithread[i]=i;
263 	    pthread_create(&tid[i], NULL, (void *)resultsthermemmt, (void *)&ithread[i]);
264 	}
265 	for(i=0; i<num_cpus; i++)  pthread_join(tid[i], NULL);
266 
267 	for(i=0;i<*nk;i++){
268 		fn[mt*i]=fn1[mt*i];
269 	}
270 	for(i=0;i<*nk;i++){
271 	    for(j=1;j<num_cpus;j++){
272 		fn[mt*i]+=fn1[mt*i+j*mt**nk];
273 	    }
274 	}
275 	SFREE(fn1);SFREE(ithread);SFREE(neapar);SFREE(nebpar);
276 
277         /* determine the internal concentrated heat flux */
278 
279 	qa[1]=qa1[1];
280 	for(j=1;j<num_cpus;j++){
281 	    qa[1]+=qa1[1+j*4];
282 	}
283 
284 	SFREE(qa1);
285 
286 	for(j=1;j<num_cpus;j++){
287 	    nal[0]+=nal[j];
288 	}
289 
290 	if(calcul_qa==1){
291 	    if(nal[0]>0){
292 		qa[1]/=nal[0];
293 	    }
294 	}
295 	SFREE(nal);
296     }
297 
298     /* calculating the thermal internal forces */
299 
300     FORTRAN(resultsforc_em,(nk,f,fn,nactdof,ipompc,nodempc,
301 			    coefmpc,labmpc,nmpc,mi,fmpc,&calcul_fn,&calcul_f,
302 			    inomat));
303 
304     /* storing results in the .dat file
305        extrapolation of integration point values to the nodes
306        interpolation of 3d results for 1d/2d elements */
307 
308     FORTRAN(resultsprint,(co,nk,kon,ipkon,lakon,ne,v,stn,inum,
309        sti,ielorien,norien,orab,t1,ithermal,filab,een,iperturb,fn,
310        nactdof,iout,vold,nodeboun,ndirboun,nboun,nmethod,ttime,xstate,
311        epn,mi,
312        nstate_,ener,enern,xstaten,eei,set,nset,istartset,iendset,
313        ialset,nprint,prlab,prset,qfx,qfn,trab,inotr,ntrans,
314        nelemload,nload,&ikin,ielmat,thicke,eme,emn,rhcon,nrhcon,shcon,
315        nshcon,cocon,ncocon,ntmat_,sideload,icfd,inomat,pslavsurf,islavact,
316        cdn,&mortar,islavnode,nslavnode,ntie,islavsurf,time,ielprop,prop,
317        veold,ne0,nmpc,ipompc,nodempc,labmpc,energyini,energy,orname,
318        xload,itiefac,pmastsurf,springarea,tieset,ipobody,ibody,xbody,
319        nbody));
320 
321   return;
322 
323 }
324 
325 /* subroutine for multithreading of resultsem */
326 
resultsemmt(ITG * i)327 void *resultsemmt(ITG *i){
328 
329     ITG nea,neb;
330 
331 /*    nedelta=(ITG)floor(*ne1/(double)num_cpus);
332     nea=*i*nedelta+1;
333     neb=(*i+1)*nedelta;
334     if((*i==num_cpus-1)&&(neb<*ne1)) neb=*ne1;*/
335 
336     nea=neapar[*i]+1;
337     neb=nebpar[*i]+1;
338 
339     FORTRAN(resultsem,(co1,kon1,ipkon1,lakon1,v1,elcon1,nelcon1,ielmat1,
340 		       ntmat1_,vini1,dtime1,matname1,mi1,ncmat1_,&nea,&neb,
341 		       sti1,alcon1,nalcon1,h01,istartset1,iendset1,ialset1,
342 		       iactive1,fn1,eei1,iout1,nmethod1));
343 
344     return NULL;
345 }
346 
347 /* subroutine for multithreading of resultstherm */
348 
resultsthermemmt(ITG * i)349 void *resultsthermemmt(ITG *i){
350 
351     ITG indexfn,indexqa,indexnal,nea,neb;
352 
353     indexfn=*i*mt1**nk1;
354     indexqa=*i*4;
355     indexnal=*i;
356 
357 /*    nedelta=(ITG)floor(*ne1/(double)num_cpus);
358     nea=*i*nedelta+1;
359     neb=(*i+1)*nedelta;
360     if((*i==num_cpus-1)&&(neb<*ne1)) neb=*ne1;*/
361 
362     nea=neapar[*i]+1;
363     neb=nebpar[*i]+1;
364 
365     FORTRAN(resultstherm,(co1,kon1,ipkon1,lakon1,v1,
366 	   elcon1,nelcon1,rhcon1,nrhcon1,ielmat1,ielorien1,norien1,orab1,
367 	   ntmat1_,t01,iperturb1,&fn1[indexfn],shcon1,nshcon1,
368 	   iout1,&qa1[indexqa],vold1,ipompc1,nodempc1,coefmpc1,nmpc1,
369            dtime1,time1,ttime1,plkcon1,nplkcon1,xstateini1,xstiff1,xstate1,
370            npmat1_,
371            matname1,mi1,ncmat1_,nstate1_,cocon1,ncocon1,
372            qfx1,ikmpc1,ilmpc1,istep1,iinc1,springarea1,
373 	   &calcul_fn1,&calcul_qa1,&nal[indexnal],&nea,&neb,ithermal1,
374            nelemload1,nload1,nmethod1,reltime1,sideload1,xload1,xloadold1,
375 	   pslavsurf1,pmastsurf1,&mortar1,clearini1,plicon1,nplicon1,
376 	   ielprop1,prop1,iponoel1,inoel1,network1,ipobody1,xbody1,ibody1));
377 
378     return NULL;
379 }
380