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 /* parallel part in resultsini.c */
19
20
21 #include <unistd.h>
22 #include <stdio.h>
23 #include <math.h>
24 #include <stdlib.h>
25 #include <pthread.h>
26 #include "CalculiX.h"
27
28 static ITG *neapar=NULL,*nebpar=NULL,*mt1,*nactdof1;
29
30 static double *b1,*v1,*veold1,*accold1,*scal11,*scal21,*cam01,*cam31;
31
iniparll(ITG * mt,ITG * nactdof,double * b,double * v,double * veold,double * accold,double * bet,double * gam,double * dtime,double * cam,ITG * nk,ITG * num_cpus)32 void iniparll(ITG *mt,ITG *nactdof,double *b,double *v,
33 double *veold,double *accold,double *bet,
34 double *gam,double *dtime,double *cam,
35 ITG *nk,ITG *num_cpus){
36
37 ITG i,idelta,isum;
38
39 /* variables for multithreading procedure */
40
41 ITG *ithread=NULL;
42
43 double scal1,scal2;
44
45 scal1=*bet**dtime**dtime;
46 scal2=*gam**dtime;
47
48 pthread_t tid[*num_cpus];
49
50 /* determining the element bounds in each thread */
51
52 NNEW(neapar,ITG,*num_cpus);
53 NNEW(nebpar,ITG,*num_cpus);
54 NNEW(cam01,double,*num_cpus);
55 NNEW(cam31,double,*num_cpus);
56
57 /* dividing the element number range into num_cpus equal numbers of
58 active entries. */
59
60 idelta=(ITG)floor(*nk/(double)(*num_cpus));
61 isum=0;
62 for(i=0;i<*num_cpus;i++){
63 neapar[i]=isum;
64 if(i!=*num_cpus-1){
65 isum+=idelta;
66 }else{
67 isum=*nk;
68 }
69 nebpar[i]=isum;
70 }
71
72 /* create threads and wait */
73
74 mt1=mt;nactdof1=nactdof;b1=b;v1=v;veold1=veold;accold1=accold;
75 scal11=&scal1;scal21=&scal2;
76
77 NNEW(ithread,ITG,*num_cpus);
78
79 for(i=0; i<*num_cpus; i++) {
80 ithread[i]=i;
81 pthread_create(&tid[i], NULL, (void *)iniparllmt, (void *)&ithread[i]);
82 }
83 for(i=0; i<*num_cpus; i++) pthread_join(tid[i], NULL);
84
85 /* determining the maximum cam[0] */
86
87 cam[0]=cam01[0];
88 cam[3]=cam31[0];
89 for(i=1;i<*num_cpus;i++){
90 if(cam01[i]>cam[0]){
91 cam[0]=cam01[i];
92 cam[3]=cam31[i];
93 }
94 }
95
96 SFREE(ithread);SFREE(neapar);SFREE(nebpar);SFREE(cam01);SFREE(cam31);
97
98 }
99
100 /* subroutine for multithreading of iniparll */
101
iniparllmt(ITG * i)102 void *iniparllmt(ITG *i){
103
104 ITG nea,neb,k,j;
105
106 double bnac;
107
108 nea=neapar[*i];
109 neb=nebpar[*i];
110
111 for(k=nea;k<neb;++k){
112 for(j=1;j<*mt1;j++){
113 if(nactdof1[*mt1*k+j]>0){
114 bnac=b1[nactdof1[*mt1*k+j]-1];
115 }else{
116 continue;
117 }
118 v1[*mt1*k+j]+=*scal11*bnac;
119 if(fabs(*scal11*bnac)>cam01[*i]){
120 cam01[*i]=fabs(*scal11*bnac);
121 cam31[*i]=nactdof1[*mt1*k+j]-0.5;
122 }
123 veold1[*mt1*k+j]+=*scal21*bnac;
124 accold1[*mt1*k+j]+=bnac;
125 }
126 }
127
128 return NULL;
129 }
130