root/src/biosav.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. biosav
  2. biotsavartmt

   1 /*     CalculiX - A 3-dimensional finite element program                 */
   2 /*              Copyright (C) 1998-2015 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;
  26 
  27 static ITG *kon1,*ipkon1,*ne1,*mi1,num_cpus,*nkapar=NULL,*nkepar=NULL;
  28 
  29 static double *co1,*qfx1,*h01;
  30 
  31 void biosav(ITG *ipkon,ITG *kon,char *lakon,ITG *ne,double *co,
  32                 double *qfx,double *h0,ITG *mi,ITG *inomat,ITG *nk){
  33 
  34     ITG i,j,*ithread=NULL,nkphi,idelta,isum;
  35 
  36     /* calculates the magnetic intensity due to currents in the phi-
  37        domain of an electromagnetic calculation */
  38       
  39     /* variables for multithreading procedure */
  40     
  41     ITG sys_cpus;
  42     char *env,*envloc,*envsys;
  43     
  44     num_cpus = 0;
  45     sys_cpus=0;
  46 
  47     /* explicit user declaration prevails */
  48 
  49     envsys=getenv("NUMBER_OF_CPUS");
  50     if(envsys){
  51         sys_cpus=atoi(envsys);
  52         if(sys_cpus<0) sys_cpus=0;
  53     }
  54 
  55     /* automatic detection of available number of processors */
  56 
  57     if(sys_cpus==0){
  58         sys_cpus = getSystemCPUs();
  59         if(sys_cpus<1) sys_cpus=1;
  60     }
  61 
  62     /* local declaration prevails, if strictly positive */
  63 
  64     envloc = getenv("CCX_NPROC_BIOTSAVART");
  65     if(envloc){
  66         num_cpus=atoi(envloc);
  67         if(num_cpus<0){
  68             num_cpus=0;
  69         }else if(num_cpus>sys_cpus){
  70             num_cpus=sys_cpus;
  71         }
  72     }
  73 
  74     /* else global declaration, if any, applies */
  75 
  76     env = getenv("OMP_NUM_THREADS");
  77     if(num_cpus==0){
  78         if (env)
  79             num_cpus = atoi(env);
  80         if (num_cpus < 1) {
  81             num_cpus=1;
  82         }else if(num_cpus>sys_cpus){
  83             num_cpus=sys_cpus;
  84         }
  85     }
  86     
  87     /* determining the nodal bounds in each thread */
  88 
  89     NNEW(nkapar,ITG,num_cpus);
  90     NNEW(nkepar,ITG,num_cpus);
  91 
  92     /* n1 is the number of nodes in the phi(magnetostatic)-domain in
  93        an electromagnetic calculation */
  94 
  95     nkphi=0;
  96     for(i=0;i<*nk;i++){
  97         if(inomat[i]==1) nkphi++;
  98     }
  99     if(nkphi<num_cpus) num_cpus=nkphi;
 100 
 101     idelta=nkphi/num_cpus;
 102     
 103     /* dividing the range from 1 to the number of phi-nodes */
 104 
 105     isum=0;
 106     for(i=0;i<num_cpus;i++){
 107         nkapar[i]=isum;
 108         if(i!=num_cpus-1){
 109             isum+=idelta;
 110         }else{
 111             isum=nkphi;
 112         }
 113         nkepar[i]=isum-1;
 114     }
 115     
 116     /* translating the bounds of the ranges to real node numbers */
 117 
 118     i=0;
 119     j=0;
 120     nkphi=-1;
 121 
 122     do{
 123         if(j==num_cpus) break;
 124         do{
 125             if(nkapar[j]==nkphi){
 126                 nkapar[j]=i;
 127                 break;
 128             }else{
 129                 do{
 130                     i++;
 131                     if(inomat[i]==1){
 132                         nkphi++;
 133                         break;
 134                     }
 135                 }while(1);
 136             }
 137         }while(1);
 138 
 139         do{
 140             if(nkepar[j]==nkphi){
 141                 nkepar[j]=i;
 142                 j++;
 143                 break;
 144             }else{
 145                 do{
 146                     i++;
 147                     if(inomat[i]==1){
 148                         nkphi++;
 149                         break;
 150                     }
 151                 }while(1);
 152             }
 153         }while(1);
 154     }while(1);
 155 
 156     ipkon1=ipkon;kon1=kon;lakon1=lakon;ne1=ne;co1=co;qfx1=qfx;
 157     h01=h0;mi1=mi;
 158     
 159     printf(" Using up to %" ITGFORMAT " cpu(s) for the Biot-Savart calculation.\n\n", num_cpus);
 160     
 161     /* create threads and wait */
 162     
 163     pthread_t tid[num_cpus];
 164     
 165     NNEW(ithread,ITG,num_cpus);
 166     for(i=0;i<num_cpus;i++){
 167         ithread[i]=i;
 168         pthread_create(&tid[i],NULL,(void *)biotsavartmt,(void *)&ithread[i]);
 169     }
 170     for(i=0;i<num_cpus;i++)pthread_join(tid[i], NULL);
 171     
 172     SFREE(ithread);SFREE(nkapar);SFREE(nkepar);
 173     
 174     return;
 175     
 176 }
 177 
 178 /* subroutine for multithreading of biotsavart */
 179 
 180 void *biotsavartmt(ITG *i){
 181 
 182     ITG nka,nkb;
 183 
 184     nka=nkapar[*i]+1;
 185     nkb=nkepar[*i]+1;
 186 
 187     FORTRAN(biotsavart,(ipkon1,kon1,lakon1,ne1,co1,qfx1,h01,mi1,&nka,
 188                         &nkb));
 189 
 190     return NULL;
 191 }
 192 

/* [<][>][^][v][top][bottom][index][help] */