/* CalculiX - A 3-dimensional finite element program */ /* Copyright (C) 1998-2007 Guido Dhondt */ /* This program is free software; you can redistribute it and/or */ /* modify it under the terms of the GNU General Public License as */ /* published by the Free Software Foundation(version 2); */ /* */ /* This program is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU General Public License for more details. */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, write to the Free Software */ /* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #include #include "CalculiX.h" #define min(a,b) ((a) <= (b) ? (a) : (b)) #define max(a,b) ((a) >= (b) ? (a) : (b)) void mastruct(int *nk, int *kon, int *ipkon, char *lakon, int *ne, int *nodeboun, int *ndirboun, int *nboun, int *ipompc, int *nodempc, int *nmpc, int *nactdof, int *icol, int *jq, int **mast1p, int **irowp, int *isolver, int *neq, int *nnn, int *ikmpc, int *ilmpc, int *ikcol, int *ipointer, int *nsky, int *nzs, int *nmethod, int *ithermal, int *ikboun, int *ilboun, int *iperturb){ int i,j,k,l,jj,ll,id,index,jdof1,jdof2,idof1,idof2,mpc1,mpc2,id1,id2, ist1,ist2,node1,node2,isubtract,nmast,ifree,istart,istartold, index1,index2,m,node,nzs_,ist,kflag,indexe,nope,isize,*mast1=NULL, *irow=NULL,icolumn,nmastboun; /* the indices in the comments follow FORTRAN convention, i.e. the fields start with 1 */ mast1=*mast1p; irow=*irowp; kflag=2; nzs_=nzs[1]; /* initialisation of nactmpc */ for(i=0;i<4**nk;++i){nactdof[i]=0;} /* determining the mechanical active degrees of freedom due to elements */ if((*ithermal<2)||(*ithermal==3)){ for(i=0;i<*ne;++i){ if(ipkon[i]<0) continue; indexe=ipkon[i]; if(strcmp1(&lakon[8*i+3],"2")==0)nope=20; else if (strcmp1(&lakon[8*i+3],"8")==0)nope=8; else if (strcmp1(&lakon[8*i+3],"10")==0)nope=10; else if (strcmp1(&lakon[8*i+3],"4")==0)nope=4; else if (strcmp1(&lakon[8*i+3],"15")==0)nope=15; else if (strcmp1(&lakon[8*i+3],"6")==0)nope=6; /* else if (strcmp1(&lakon[8*i],"E")==0)nope=4;*/ else if (strcmp1(&lakon[8*i],"E")==0)nope=atoi(&lakon[8*i+7]); else continue; for(j=0;j1){ for(i=0;i<*ne;++i){ if(ipkon[i]<0) continue; indexe=ipkon[i]; if(strcmp1(&lakon[8*i+3],"2")==0)nope=20; else if (strcmp1(&lakon[8*i+3],"8")==0)nope=8; else if (strcmp1(&lakon[8*i+3],"10")==0)nope=10; else if (strcmp1(&lakon[8*i+3],"4")==0)nope=4; else if (strcmp1(&lakon[8*i+3],"15")==0)nope=15; else if (strcmp1(&lakon[8*i+3],"6")==0)nope=6; else continue; for(j=0;j3){continue;} nactdof[4*(nodeboun[i]-1)+ndirboun[i]]=0; } for(i=0;i<*nmpc;++i){ index=ipompc[i]-1; nactdof[4*nodempc[3*index]+nodempc[3*index+1]-4]=0; } /* numbering the active degrees of freedom */ neq[0]=0; for(i=0;i<*nk;++i){ for(j=1;j<4;++j){ if(nactdof[4*nnn[i]+j-4]!=0){ if((*ithermal<2)||(*ithermal==3)){ ++neq[0]; nactdof[4*nnn[i]+j-4]=neq[0]; } else{ nactdof[4*nnn[i]+j-4]=0; } } } } neq[1]=neq[0]; for(i=0;i<*nk;++i){ if(nactdof[4*nnn[i]-4]!=0){ if(*ithermal>1){ ++neq[1]; nactdof[4*nnn[i]-4]=neq[1]; } else{ nactdof[4*nnn[i]-4]=0; } } } if((*nmethod==2)||((*nmethod==4)&&(*iperturb<=1))||(*nmethod>=5)){ neq[2]=neq[1]+*nboun; } else{neq[2]=neq[1];} ifree=0; /*for(i=0;i<4**nk;++i){printf("nactdof=%d,%d,%d\n",i/4+1,i-(i/4)*4,nactdof[i]);}*/ /* determining the position of each nonzero matrix element mast1(ipointer(i)) = first nonzero row in column i irow(ipointer(i)) points to further nonzero elements in column i */ for(i=0;i<4**nk;++i){ipointer[i]=0;} /* mechanical entries */ if((*ithermal<2)||(*ithermal==3)){ for(i=0;i<*ne;++i){ if(ipkon[i]<0) continue; indexe=ipkon[i]; if(strcmp1(&lakon[8*i+3],"2")==0)nope=20; else if (strcmp1(&lakon[8*i+3],"8")==0)nope=8; else if (strcmp1(&lakon[8*i+3],"10")==0)nope=10; else if (strcmp1(&lakon[8*i+3],"4")==0)nope=4; else if (strcmp1(&lakon[8*i+3],"15")==0)nope=15; else if (strcmp1(&lakon[8*i+3],"6")==0)nope=6; /* else if (strcmp1(&lakon[8*i],"E")==0)nope=4;*/ else if (strcmp1(&lakon[8*i],"E")==0)nope=atoi(&lakon[8*i+7]); else continue; for(jj=0;jj<3*nope;++jj){ j=jj/3; k=jj-3*j; node1=kon[indexe+j]; jdof1=nactdof[4*(node1-1)+k+1]; for(ll=jj;ll<3*nope;++ll){ l=ll/3; m=ll-3*l; node2=kon[indexe+l]; jdof2=nactdof[4*(node2-1)+m+1]; /* check whether one of the DOF belongs to a SPC or MPC */ if((jdof1!=0)&&(jdof2!=0)){ insert(ipointer,&mast1,&irow,&jdof1,&jdof2,&ifree,&nzs_); } else if((jdof1!=0)||(jdof2!=0)){ /* idof1: genuine DOF idof2: nominal DOF of the SPC/MPC */ if(jdof1==0){ idof1=jdof2; idof2=7*node1+k-6;} else{ idof1=jdof1; idof2=7*node2+m-6;} if(*nmpc>0){ FORTRAN(nident,(ikmpc,&idof2,nmpc,&id)); if((id>0)&&(ikmpc[id-1]==idof2)){ /* regular DOF / MPC */ id=ilmpc[id-1]; ist=ipompc[id-1]; index=nodempc[3*ist-1]; if(index==0) continue; while(1){ idof2=nactdof[4*nodempc[3*index-3]+nodempc[3*index-2]-4]; if(idof2!=0){ insert(ipointer,&mast1,&irow,&idof1,&idof2,&ifree,&nzs_); } index=nodempc[3*index-1]; if(index==0) break; } continue; } } /* boundary stiffness coefficients (for frequency and modal dynamic calculations) */ if((*nmethod==2)||((*nmethod==4)&&(*iperturb<=1))||(*nmethod>=5)){ FORTRAN(nident,(ikboun,&idof2,nboun,&id)); icolumn=neq[1]+ilboun[id-1]; /* printf("idof1=%d,icolumn=%d\n",idof1,icolumn);*/ insert(ipointer,&mast1,&irow,&idof1,&icolumn,&ifree,&nzs_); } } else{ idof1=7*node1+k-6; idof2=7*node2+m-6; mpc1=0; mpc2=0; if(*nmpc>0){ FORTRAN(nident,(ikmpc,&idof1,nmpc,&id1)); if((id1>0)&&(ikmpc[id1-1]==idof1)) mpc1=1; FORTRAN(nident,(ikmpc,&idof2,nmpc,&id2)); if((id2>0)&&(ikmpc[id2-1]==idof2)) mpc2=1; } if((mpc1==1)&&(mpc2==1)){ id1=ilmpc[id1-1]; id2=ilmpc[id2-1]; if(id1==id2){ /* MPC id1 / MPC id1 */ ist=ipompc[id1-1]; index1=nodempc[3*ist-1]; if(index1==0) continue; while(1){ idof1=nactdof[4*nodempc[3*index1-3]+nodempc[3*index1-2]-4]; index2=index1; while(1){ idof2=nactdof[4*nodempc[3*index2-3]+nodempc[3*index2-2]-4]; if((idof1!=0)&&(idof2!=0)){ insert(ipointer,&mast1,&irow,&idof1,&idof2,&ifree,&nzs_);} index2=nodempc[3*index2-1]; if(index2==0) break; } index1=nodempc[3*index1-1]; if(index1==0) break; } } else{ /* MPC id1 /MPC id2 */ ist1=ipompc[id1-1]; index1=nodempc[3*ist1-1]; if(index1==0) continue; while(1){ idof1=nactdof[4*nodempc[3*index1-3]+nodempc[3*index1-2]-4]; ist2=ipompc[id2-1]; index2=nodempc[3*ist2-1]; if(index2==0){ index1=nodempc[3*index1-1]; if(index1==0){break;} else{continue;} } while(1){ idof2=nactdof[4*nodempc[3*index2-3]+nodempc[3*index2-2]-4]; if((idof1!=0)&&(idof2!=0)){ insert(ipointer,&mast1,&irow,&idof1,&idof2,&ifree,&nzs_);} index2=nodempc[3*index2-1]; if(index2==0) break; } index1=nodempc[3*index1-1]; if(index1==0) break; } } } } } } } } /* nzs[0]=ifree-neq[0];*/ /* printf("\nneq[0]=%d,nzs[0]=%d\n\n",neq[0],nzs[0]);*/ /* thermal entries*/ if(*ithermal>1){ for(i=0;i<*ne;++i){ if(ipkon[i]<0) continue; indexe=ipkon[i]; if(strcmp1(&lakon[8*i+3],"2")==0)nope=20; else if (strcmp1(&lakon[8*i+3],"8")==0)nope=8; else if (strcmp1(&lakon[8*i+3],"10")==0)nope=10; else if (strcmp1(&lakon[8*i+3],"4")==0)nope=4; else if (strcmp1(&lakon[8*i+3],"15")==0)nope=15; else if (strcmp1(&lakon[8*i+3],"6")==0)nope=6; else continue; for(jj=0;jj0){ FORTRAN(nident,(ikmpc,&idof2,nmpc,&id)); if((id>0)&&(ikmpc[id-1]==idof2)){ /* regular DOF / MPC */ id=ilmpc[id-1]; ist=ipompc[id-1]; index=nodempc[3*ist-1]; if(index==0) continue; while(1){ idof2=nactdof[4*nodempc[3*index-3]+nodempc[3*index-2]-4]; if(idof2!=0){ insert(ipointer,&mast1,&irow,&idof1,&idof2,&ifree,&nzs_); } index=nodempc[3*index-1]; if(index==0) break; } continue; } } /* boundary stiffness coefficients (for frequency and modal dynamic calculations */ if((*nmethod==2)||((*nmethod==4)&&(*iperturb<=1))||(*nmethod>=5)){ FORTRAN(nident,(ikboun,&idof2,nboun,&id)); icolumn=neq[1]+ilboun[id-1]; insert(ipointer,&mast1,&irow,&idof1,&icolumn,&ifree,&nzs_); } } else{ idof1=7*node1-7; idof2=7*node2-7; mpc1=0; mpc2=0; if(*nmpc>0){ FORTRAN(nident,(ikmpc,&idof1,nmpc,&id1)); if((id1>0)&&(ikmpc[id1-1]==idof1)) mpc1=1; FORTRAN(nident,(ikmpc,&idof2,nmpc,&id2)); if((id2>0)&&(ikmpc[id2-1]==idof2)) mpc2=1; } if((mpc1==1)&&(mpc2==1)){ id1=ilmpc[id1-1]; id2=ilmpc[id2-1]; if(id1==id2){ /* MPC id1 / MPC id1 */ ist=ipompc[id1-1]; index1=nodempc[3*ist-1]; if(index1==0) continue; while(1){ idof1=nactdof[4*nodempc[3*index1-3]+nodempc[3*index1-2]-4]; index2=index1; while(1){ idof2=nactdof[4*nodempc[3*index2-3]+nodempc[3*index2-2]-4]; if((idof1!=0)&&(idof2!=0)){ insert(ipointer,&mast1,&irow,&idof1,&idof2,&ifree,&nzs_);} index2=nodempc[3*index2-1]; if(index2==0) break; } index1=nodempc[3*index1-1]; if(index1==0) break; } } else{ /* MPC id1 /MPC id2 */ ist1=ipompc[id1-1]; index1=nodempc[3*ist1-1]; if(index1==0) continue; while(1){ idof1=nactdof[4*nodempc[3*index1-3]+nodempc[3*index1-2]-4]; ist2=ipompc[id2-1]; index2=nodempc[3*ist2-1]; if(index2==0){ index1=nodempc[3*index1-1]; if(index1==0){break;} else{continue;} } while(1){ idof2=nactdof[4*nodempc[3*index2-3]+nodempc[3*index2-2]-4]; if((idof1!=0)&&(idof2!=0)){ insert(ipointer,&mast1,&irow,&idof1,&idof2,&ifree,&nzs_);} index2=nodempc[3*index2-1]; if(index2==0) break; } index1=nodempc[3*index1-1]; if(index1==0) break; } } } } } } } } /* ordering the nonzero nodes in the SUPERdiagonal columns mast1 contains the row numbers column per column, irow the column numbers */ /* for(i=0;i=neq[1]) continue; printf("*ERROR in mastruct: zero column\n"); FORTRAN(stop,()); } istart=ipointer[i]; while(1){ istartold=istart; istart=irow[istart-1]; irow[istartold-1]=i+1; if(istart==0) break; } } /* defining icol and jq */ if(neq[1]==0){ printf("\n*WARNING: no degrees of freedom in the model\n\n"); } nmast=ifree; /* for frequency calculations and modal dynamic calculations: sorting column after column; determining the end of the classical stiffness matrix in fields irow and mast1 */ if((*nmethod==2)||((*nmethod==4)&&(*iperturb<=1))||(*nmethod>=5)){ FORTRAN(isortii,(irow,mast1,&nmast,&kflag)); nmastboun=nmast; FORTRAN(nident,(irow,&neq[1],&nmast,&id)); if((id>0)&&(irow[id-1]==neq[1])) nmast=id; } /* summary */ printf(" number of equations\n"); printf(" %d\n",neq[1]); printf(" number of nonzero matrix elements\n"); printf(" %d\n",nmast); printf("\n"); /* changing the meaning of icol,j1,mast1,irow: - irow is going to contain the row numbers of the SUBdiagonal nonzero's, column per column - mast1 contains the column numbers - icol(i)=# SUBdiagonal nonzero's in column i - jq(i)= location in field irow of the first SUBdiagonal nonzero in column i */ /* switching from a SUPERdiagonal inventory to a SUBdiagonal one */ FORTRAN(isortii,(mast1,irow,&nmast,&kflag)); /* filtering out the diagonal elements and generating icol and jq */ isubtract=0; for(i=0;i0){ isize=jq[i+1]-jq[i]; FORTRAN(isortii,(&irow[jq[i]-1],&mast1[jq[i]-1],&isize,&kflag)); } } if(neq[0]==0){nzs[0]=0;} else{nzs[0]=jq[neq[0]]-1;} nzs[1]=jq[neq[1]]-1; /* determining jq for the boundary stiffness matrix (only for frequency and modal dynamic calculations */ if((*nmethod==2)||((*nmethod==4)&&(*iperturb<=1))||(*nmethod>=5)){ for(i=neq[1];i0){ isize=jq[i+1]-jq[i]; FORTRAN(isortii,(&irow[jq[i]-1],&mast1[jq[i]-1],&isize,&kflag)); } } nzs[2]=jq[neq[2]]-1; } else{nzs[2]=nzs[1];} /* for(i=nzs[1];i