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