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;
26 
27 static ITG *kon1,*ipkon1,*ne1,*nelcon1,*nrhcon1,*nalcon1,*ielmat1,*ielorien1,
28   *norien1,*ntmat1_,*ithermal1,*iprestr1,*iperturb1,*iout1,*nmethod1,
29   *nplicon1,*nplkcon1,*npmat1_,*mi1,*ielas1,*icmd1,*ncmat1_,*nstate1_,
30   *istep1,*iinc1,calcul_fn1,calcul_qa1,calcul_cauchy1,*nener1,ikin1,
31   *nal=NULL,num_cpus,mt1,*nk1,*ne01,*mortar1,*ielprop1,*kscale1,*neapar1,
32   *nebpar1,mscalmethod1=0,*irowtloc1=NULL,*jqtloc1=NULL,*islavelinv1=NULL,
33   mortartrafoflag1=0,intscheme1=0;
34 
35 static double *co1,*v1,*stx1,*elcon1,*rhcon1,*alcon1,*alzero1,*orab1,*t01,*t11,
36   *prestr1,*eme1,*fn1=NULL,*qa1=NULL,*vold1,*veold1,*dtime1,*time1,
37   *ttime1,*plicon1,*plkcon1,*xstateini1,*xstiff1,*xstate1,*stiini1,
38   *vini1,*ener1,*eei1,*enerini1,*springarea1,*reltime1,
39   *thicke1,*emeini1,*prop1,*pslavsurf1,*pmastsurf1,*clearini1,*smscale1,
40   *energysms1=NULL,*t0g1,*t1g1,*autloc1=NULL;
41 
resultsstr(double * co,ITG * nk,ITG * kon,ITG * ipkon,char * lakon,ITG * ne,double * v,double * stn,ITG * inum,double * stx,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 * stiini,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 * pslavsurf,double * pmastsurf,ITG * mortar,ITG * islavact,double * cdn,ITG * islavnode,ITG * nslavnode,ITG * ntie,double * clearini,ITG * islavsurf,ITG * ielprop,double * prop,double * energyini,double * energy,ITG * kscale,ITG * nener,char * orname,ITG * network,ITG * neapar,ITG * nebpar,ITG * ipobody,ITG * ibody,double * xbody,ITG * nbody)42 void resultsstr(double *co,ITG *nk,ITG *kon,ITG *ipkon,char *lakon,ITG *ne,
43 		double *v,double *stn,ITG *inum,double *stx,double *elcon,
44 		ITG *nelcon,double *rhcon,ITG *nrhcon,double *alcon,
45 		ITG *nalcon,double *alzero,ITG *ielmat,ITG *ielorien,
46 		ITG *norien,double *orab,ITG *ntmat_,double *t0,double *t1,
47 		ITG *ithermal,double *prestr,ITG *iprestr,char *filab,
48 		double *eme,double *emn,double *een,ITG *iperturb,double *f,
49 		double *fn,ITG *nactdof,ITG *iout,double *qa,double *vold,
50 		double *b,ITG *nodeboun,ITG *ndirboun,double *xboun,ITG *nboun,
51 		ITG *ipompc,ITG *nodempc,double *coefmpc,char *labmpc,
52 		ITG *nmpc,ITG *nmethod,double *cam,ITG *neq,double *veold,
53 		double *accold,double *bet,double *gam,double *dtime,
54 		double *time,double *ttime,double *plicon,ITG *nplicon,
55 		double *plkcon,ITG *nplkcon,double *xstateini,double *xstiff,
56 		double *xstate,ITG *npmat_,double *epn,char *matname,ITG *mi,
57 		ITG *ielas,ITG *icmd,ITG *ncmat_,ITG *nstate_,double *stiini,
58 		double *vini,ITG *ikboun,ITG *ilboun,double *ener,
59 		double *enern,double *emeini,double *xstaten,double *eei,
60 		double *enerini,double *cocon,ITG *ncocon,char *set,ITG *nset,
61 		ITG *istartset,ITG *iendset,ITG *ialset,ITG *nprint,
62 		char *prlab,char *prset,double *qfx,double *qfn,double *trab,
63 		ITG *inotr,ITG *ntrans,double *fmpc,ITG *nelemload,ITG *nload,
64 		ITG *ikmpc,ITG *ilmpc,ITG *istep,ITG *iinc,double *springarea,
65 		double *reltime,ITG *ne0,double *xforc,ITG *nforc,
66 		double *thicke,double *shcon,ITG *nshcon,char *sideload,
67 		double *xload,double *xloadold,ITG *icfd,ITG *inomat,
68 		double *pslavsurf,double *pmastsurf,ITG *mortar,ITG *islavact,
69 		double *cdn,ITG *islavnode,ITG *nslavnode,ITG *ntie,
70 		double *clearini,ITG *islavsurf,ITG *ielprop,double *prop,
71 		double *energyini,double *energy,ITG *kscale,ITG *nener,
72 		char *orname,ITG *network,ITG *neapar,ITG *nebpar,
73 		ITG *ipobody,ITG *ibody,double *xbody,ITG *nbody){
74 
75   char *tieset=NULL;
76 
77   ITG intpointvarm,calcul_fn,calcul_f,calcul_qa,calcul_cauchy,ikin,
78     mt=mi[1]+1,i,j,*itiefac=NULL;
79 
80   double *t0g=NULL,*t1g=NULL;
81 
82   /*
83 
84     calculating the stress integration point values
85 
86     iout=2: v is assumed to be known and is used to
87     calculate strains, stresses..., requested results output */
88 
89   /* variables for multithreading procedure */
90 
91   ITG sys_cpus,*ithread=NULL;
92   char *env,*envloc,*envsys;
93 
94   num_cpus = 0;
95   sys_cpus=0;
96 
97   /* explicit user declaration prevails */
98 
99   envsys=getenv("NUMBER_OF_CPUS");
100   if(envsys){
101     sys_cpus=atoi(envsys);
102     if(sys_cpus<0) sys_cpus=0;
103   }
104 
105   /* automatic detection of available number of processors */
106 
107   if(sys_cpus==0){
108     sys_cpus = getSystemCPUs();
109     if(sys_cpus<1) sys_cpus=1;
110   }
111 
112   /* local declaration prevails, if strictly positive */
113 
114   envloc = getenv("CCX_NPROC_SENS");
115   if(envloc){
116     num_cpus=atoi(envloc);
117     if(num_cpus<0){
118       num_cpus=0;
119     }else if(num_cpus>sys_cpus){
120       num_cpus=sys_cpus;
121     }
122 
123   }
124 
125   /* else global declaration, if any, applies */
126 
127   env = getenv("OMP_NUM_THREADS");
128   if(num_cpus==0){
129     if (env)
130       num_cpus = atoi(env);
131     if (num_cpus < 1) {
132       num_cpus=1;
133     }else if(num_cpus>sys_cpus){
134       num_cpus=sys_cpus;
135     }
136   }
137 
138   // next line is to be inserted in a similar way for all other paralell parts
139 
140   if(*ne<num_cpus) num_cpus=*ne;
141 
142   pthread_t tid[num_cpus];
143 
144   /* setting the output variables */
145 
146   calcul_fn=0;
147   calcul_f=0;
148   calcul_qa=0;
149   if(iperturb[1]==1){calcul_cauchy=1;}else{calcul_cauchy=0;}
150 
151   qa[0]=0.e0;
152   qa[1]=0.e0;
153   intpointvarm=1;
154   ikin=0;
155 
156   /* calculating the stresses and material tangent at the
157      integration points; calculating the internal forces */
158 
159   if(((ithermal[0]<=1)||(ithermal[0]>=3))&&(intpointvarm==1)){
160 
161     NNEW(fn1,double,num_cpus*mt**nk);
162     NNEW(qa1,double,num_cpus*4);
163     NNEW(nal,ITG,num_cpus);
164     NNEW(energysms1,double,num_cpus);
165 
166     co1=co;kon1=kon;ipkon1=ipkon;lakon1=lakon;ne1=ne;v1=v;
167     stx1=stx;elcon1=elcon;nelcon1=nelcon;rhcon1=rhcon;
168     nrhcon1=nrhcon;alcon1=alcon;nalcon1=nalcon;alzero1=alzero;
169     ielmat1=ielmat;ielorien1=ielorien;norien1=norien;orab1=orab;
170     ntmat1_=ntmat_;t01=t0;t11=t1;ithermal1=ithermal;prestr1=prestr;
171     iprestr1=iprestr;eme1=eme;iperturb1=iperturb;iout1=iout;
172     vold1=vold;nmethod1=nmethod;veold1=veold;dtime1=dtime;
173     time1=time;ttime1=ttime;plicon1=plicon;nplicon1=nplicon;
174     plkcon1=plkcon;nplkcon1=nplkcon;xstateini1=xstateini;
175     xstiff1=xstiff;xstate1=xstate;npmat1_=npmat_;matname1=matname;
176     mi1=mi;ielas1=ielas;icmd1=icmd;ncmat1_=ncmat_;nstate1_=nstate_;
177     stiini1=stiini;vini1=vini;ener1=ener;eei1=eei;enerini1=enerini;
178     istep1=istep;iinc1=iinc;springarea1=springarea;reltime1=reltime;
179     calcul_fn1=calcul_fn;calcul_qa1=calcul_qa;calcul_cauchy1=calcul_cauchy;
180     nener1=nener;ikin1=ikin;mt1=mt;nk1=nk;ne01=ne0;thicke1=thicke;
181     emeini1=emeini;pslavsurf1=pslavsurf;clearini1=clearini;
182     pmastsurf1=pmastsurf;mortar1=mortar;ielprop1=ielprop;prop1=prop;
183     kscale1=kscale;neapar1=neapar;nebpar1=nebpar;t0g1=t0g;t1g1=t1g;
184 
185     /* calculating the stresses */
186 
187     if(((*nmethod!=4)&&(*nmethod!=5))||(iperturb[0]>1)){
188       printf(" Using up to %" ITGFORMAT " cpu(s) for the stress calculation.\n\n", num_cpus);
189     }
190 
191     /* create threads and wait */
192 
193     NNEW(ithread,ITG,num_cpus);
194     for(i=0; i<num_cpus; i++)  {
195       ithread[i]=i;
196       pthread_create(&tid[i], NULL, (void *)resultsmechmtstr, (void *)&ithread[i]);
197     }
198     for(i=0; i<num_cpus; i++)  pthread_join(tid[i], NULL);
199 
200     for(i=0;i<mt**nk;i++){
201       fn[i]=fn1[i];
202     }
203     for(i=0;i<mt**nk;i++){
204       for(j=1;j<num_cpus;j++){
205 	fn[i]+=fn1[i+j*mt**nk];
206       }
207     }
208     SFREE(fn1);SFREE(ithread);
209 
210     /* determine the internal force */
211 
212     qa[0]=qa1[0];
213     for(j=1;j<num_cpus;j++){
214       qa[0]+=qa1[j*4];
215     }
216 
217     /* determine the decrease of the time increment in case
218        the material routine diverged */
219 
220     for(j=0;j<num_cpus;j++){
221       if(qa1[2+j*4]>0.){
222 	if(qa[2]<0.){
223 	  qa[2]=qa1[2+j*4];
224 	}else{
225 	  if(qa1[2+j*4]<qa[2]){qa[2]=qa1[2+j*4];}
226 	}
227       }
228     }
229 
230     SFREE(qa1);
231 
232     for(j=1;j<num_cpus;j++){
233       nal[0]+=nal[j];
234     }
235 
236     if(calcul_qa==1){
237       if(nal[0]>0){
238 	qa[0]/=nal[0];
239       }
240     }
241     SFREE(nal);
242 
243     /* add up additional kinetic energy through mass scaling:
244        not needed since no mass scaling */
245 
246     SFREE(energysms1);
247   }
248 
249   /* storing results in the .dat file
250      extrapolation of integration point values to the nodes
251      interpolation of 3d results for 1d/2d elements */
252 
253   FORTRAN(resultsprint,(co,nk,kon,ipkon,lakon,ne,v,stn,inum,
254 			stx,ielorien,norien,orab,t1,ithermal,filab,een,iperturb,fn,
255 			nactdof,iout,vold,nodeboun,ndirboun,nboun,nmethod,ttime,xstate,
256 			epn,mi,
257 			nstate_,ener,enern,xstaten,eei,set,nset,istartset,iendset,
258 			ialset,nprint,prlab,prset,qfx,qfn,trab,inotr,ntrans,
259 			nelemload,nload,&ikin,ielmat,thicke,eme,emn,rhcon,nrhcon,shcon,
260 			nshcon,cocon,ncocon,ntmat_,sideload,icfd,inomat,pslavsurf,islavact,
261 			cdn,mortar,islavnode,nslavnode,ntie,islavsurf,time,ielprop,prop,
262 			veold,ne0,nmpc,ipompc,nodempc,labmpc,energyini,energy,orname,
263 			xload,itiefac,pmastsurf,springarea,tieset,ipobody,ibody,xbody,
264 			nbody));
265 
266   return;
267 
268 }
269 
270 /* subroutine for multithreading of resultsmech */
271 
resultsmechmtstr(ITG * i)272 void *resultsmechmtstr(ITG *i){
273 
274   ITG indexfn,indexqa,indexnal,nea,neb,nedelta,list,*ilist=NULL;
275 
276   indexfn=*i*mt1**nk1;
277   indexqa=*i*4;
278   indexnal=*i;
279 
280   nedelta=(ITG)floor(*ne1/(double)num_cpus);
281 
282   nea=neapar1[*i]+1;
283   neb=nebpar1[*i]+1;
284 
285   if((*i==num_cpus-1)&&(neb<*ne1)) neb=*ne1;
286 
287   list=0;
288   FORTRAN(resultsmech,(co1,kon1,ipkon1,lakon1,ne1,v1,
289 		       stx1,elcon1,nelcon1,rhcon1,nrhcon1,alcon1,nalcon1,
290 		       alzero1,
291 		       ielmat1,ielorien1,norien1,orab1,ntmat1_,t01,t11,
292 		       ithermal1,prestr1,
293 		       iprestr1,eme1,iperturb1,&fn1[indexfn],iout1,
294 		       &qa1[indexqa],vold1,
295 		       nmethod1,
296 		       veold1,dtime1,time1,ttime1,plicon1,nplicon1,plkcon1,
297 		       nplkcon1,
298 		       xstateini1,xstiff1,xstate1,npmat1_,matname1,mi1,ielas1,
299 		       icmd1,
300 		       ncmat1_,nstate1_,stiini1,vini1,ener1,eei1,enerini1,
301 		       istep1,iinc1,
302 		       springarea1,reltime1,&calcul_fn1,&calcul_qa1,
303 		       &calcul_cauchy1,nener1,
304 		       &ikin1,&nal[indexnal],ne01,thicke1,emeini1,
305 		       pslavsurf1,pmastsurf1,mortar1,clearini1,&nea,&neb,
306 		       ielprop1,prop1,
307 		       kscale1,&list,ilist,smscale1,&mscalmethod1,
308 		       &energysms1[indexnal],
309 		       t0g1,t1g1,islavelinv1,autloc1,irowtloc1,jqtloc1,
310 		       &mortartrafoflag1,&intscheme1));
311 
312   return NULL;
313 }
314