1 2 #include <engine.h> /* Matlab include file */ 3 #include <petscsys.h> 4 #include <petscmatlab.h> /*I "petscmatlab.h" I*/ 5 #include <petsc/private/petscimpl.h> 6 7 struct _p_PetscMatlabEngine { 8 PETSCHEADER(int); 9 Engine *ep; 10 char buffer[1024]; 11 }; 12 13 PetscClassId MATLABENGINE_CLASSID = -1; 14 15 /*@C 16 PetscMatlabEngineCreate - Creates a MATLAB engine object 17 18 Not Collective 19 20 Input Parameters: 21 + comm - a separate MATLAB engine is started for each process in the communicator 22 - machine - name of machine where MATLAB engine is to be run (usually NULL) 23 24 Output Parameter: 25 . mengine - the resulting object 26 27 Options Database: 28 . -matlab_engine_graphics - allow the MATLAB engine to display graphics 29 30 Level: advanced 31 32 .seealso: PetscMatlabEngineDestroy(), PetscMatlabEnginePut(), PetscMatlabEngineGet(), 33 PetscMatlabEngineEvaluate(), PetscMatlabEngineGetOutput(), PetscMatlabEnginePrintOutput(), 34 PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePutArray(), PetscMatlabEngineGetArray(), PetscMatlabEngine 35 @*/ 36 PetscErrorCode PetscMatlabEngineCreate(MPI_Comm comm,const char machine[],PetscMatlabEngine *mengine) 37 { 38 PetscErrorCode ierr; 39 PetscMPIInt rank,size; 40 char buffer[256]; 41 PetscMatlabEngine e; 42 PetscBool flg = PETSC_FALSE,mgiven = PETSC_TRUE; 43 44 PetscFunctionBegin; 45 if (MATLABENGINE_CLASSID == -1) { 46 ierr = PetscClassIdRegister("MATLAB Engine",&MATLABENGINE_CLASSID);CHKERRQ(ierr); 47 } 48 ierr = PetscOptionsGetBool(NULL,NULL,"-matlab_engine_graphics",&flg,NULL);CHKERRQ(ierr); 49 50 ierr = PetscHeaderCreate(e,MATLABENGINE_CLASSID,"MatlabEngine","MATLAB Engine","Sys",comm,PetscMatlabEngineDestroy,NULL);CHKERRQ(ierr); 51 52 if (!machine) { 53 machine = "\0"; 54 mgiven = PETSC_FALSE; 55 } 56 ierr = PetscStrncpy(buffer,PETSC_MATLAB_COMMAND,sizeof(buffer));CHKERRQ(ierr); 57 if (!flg) { 58 ierr = PetscStrlcat(buffer," -nodisplay ",sizeof(buffer));CHKERRQ(ierr); 59 } 60 ierr = PetscStrlcat(buffer," -nosplash ",sizeof(buffer));CHKERRQ(ierr); 61 if (mgiven) { 62 ierr = PetscInfo2(0,"Starting MATLAB engine on %s with command %s\n",machine,buffer);CHKERRQ(ierr); 63 } else { 64 ierr = PetscInfo1(0,"Starting MATLAB engine with command %s\n",buffer);CHKERRQ(ierr); 65 } 66 e->ep = engOpen(buffer); 67 if (!e->ep) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Unable to start MATLAB engine on %s",machine); 68 engOutputBuffer(e->ep,e->buffer,1024); 69 70 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 71 ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 72 sprintf(buffer,"MPI_Comm_rank = %d; MPI_Comm_size = %d;\n",rank,size); 73 engEvalString(e->ep, buffer); 74 if (mgiven) { 75 ierr = PetscInfo1(0,"Started MATLAB engine on %s\n",machine);CHKERRQ(ierr); 76 } else { 77 ierr = PetscInfo(0,"Started MATLAB engine\n");CHKERRQ(ierr); 78 } 79 *mengine = e; 80 PetscFunctionReturn(0); 81 } 82 83 /*@ 84 PetscMatlabEngineDestroy - Shuts down a Matlab engine. 85 86 Collective on PetscMatlabEngine 87 88 Input Parameters: 89 . e - the engine 90 91 Level: advanced 92 93 .seealso: PetscMatlabEngineCreate(), PetscMatlabEnginePut(), PetscMatlabEngineGet(), 94 PetscMatlabEngineEvaluate(), PetscMatlabEngineGetOutput(), PetscMatlabEnginePrintOutput(), 95 PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePutArray(), PetscMatlabEngineGetArray(), PetscMatlabEngine 96 @*/ 97 PetscErrorCode PetscMatlabEngineDestroy(PetscMatlabEngine *v) 98 { 99 PetscErrorCode ierr; 100 101 PetscFunctionBegin; 102 if (!*v) PetscFunctionReturn(0); 103 PetscValidHeaderSpecific(*v,MATLABENGINE_CLASSID,1); 104 if (--((PetscObject)(*v))->refct > 0) PetscFunctionReturn(0); 105 ierr = PetscInfo(0,"Stopping MATLAB engine\n");CHKERRQ(ierr); 106 ierr = engClose((*v)->ep); 107 if (ierr) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error closing Matlab engine"); 108 ierr = PetscInfo(0,"MATLAB engine stopped\n");CHKERRQ(ierr); 109 ierr = PetscHeaderDestroy(v);CHKERRQ(ierr); 110 PetscFunctionReturn(0); 111 } 112 113 /*@C 114 PetscMatlabEngineEvaluate - Evaluates a string in MATLAB 115 116 Not Collective 117 118 Input Parameters: 119 + mengine - the MATLAB engine 120 - string - format as in a printf() 121 122 Level: advanced 123 124 .seealso: PetscMatlabEngineDestroy(), PetscMatlabEnginePut(), PetscMatlabEngineGet(), 125 PetscMatlabEngineCreate(), PetscMatlabEngineGetOutput(), PetscMatlabEnginePrintOutput(), 126 PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePutArray(), PetscMatlabEngineGetArray(), PetscMatlabEngine 127 @*/ 128 PetscErrorCode PetscMatlabEngineEvaluate(PetscMatlabEngine mengine,const char string[],...) 129 { 130 va_list Argp; 131 char buffer[1024]; 132 PetscErrorCode ierr; 133 size_t fullLength; 134 135 PetscFunctionBegin; 136 va_start(Argp,string); 137 ierr = PetscVSNPrintf(buffer,1024-9-5,string,&fullLength,Argp);CHKERRQ(ierr); 138 va_end(Argp); 139 140 ierr = PetscInfo1(0,"Evaluating MATLAB string: %s\n",buffer);CHKERRQ(ierr); 141 engEvalString(mengine->ep, buffer); 142 143 /* 144 Check for error in MATLAB: indicated by ? as first character in engine->buffer 145 */ 146 if (mengine->buffer[4] == '?') SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in evaluating MATLAB command:%s\n%s",string,mengine->buffer); 147 148 ierr = PetscInfo1(0,"Done evaluating Matlab string: %s\n",buffer);CHKERRQ(ierr); 149 PetscFunctionReturn(0); 150 } 151 152 /*@C 153 PetscMatlabEngineGetOutput - Gets a string buffer where the MATLAB output is 154 printed 155 156 Not Collective 157 158 Input Parameter: 159 . mengine - the MATLAB engine 160 161 Output Parameter: 162 . string - buffer where MATLAB output is printed 163 164 Level: advanced 165 166 .seealso: PetscMatlabEngineDestroy(), PetscMatlabEnginePut(), PetscMatlabEngineGet(), 167 PetscMatlabEngineEvaluate(), PetscMatlabEngineCreate(), PetscMatlabEnginePrintOutput(), 168 PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePutArray(), PetscMatlabEngineGetArray(), PetscMatlabEngine 169 @*/ 170 PetscErrorCode PetscMatlabEngineGetOutput(PetscMatlabEngine mengine,char **string) 171 { 172 PetscFunctionBegin; 173 *string = mengine->buffer; 174 PetscFunctionReturn(0); 175 } 176 177 /*@C 178 PetscMatlabEnginePrintOutput - prints the output from MATLAB 179 180 Collective on PetscMatlabEngine 181 182 Input Parameters: 183 . mengine - the Matlab engine 184 185 Level: advanced 186 187 .seealso: PetscMatlabEngineDestroy(), PetscMatlabEnginePut(), PetscMatlabEngineGet(), 188 PetscMatlabEngineEvaluate(), PetscMatlabEngineGetOutput(), PetscMatlabEngineCreate(), 189 PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePutArray(), PetscMatlabEngineGetArray(), PetscMatlabEngine 190 @*/ 191 PetscErrorCode PetscMatlabEnginePrintOutput(PetscMatlabEngine mengine,FILE *fd) 192 { 193 PetscErrorCode ierr; 194 PetscMPIInt rank; 195 196 PetscFunctionBegin; 197 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)mengine),&rank);CHKERRQ(ierr); 198 ierr = PetscSynchronizedFPrintf(PetscObjectComm((PetscObject)mengine),fd,"[%d]%s",rank,mengine->buffer);CHKERRQ(ierr); 199 ierr = PetscSynchronizedFlush(PetscObjectComm((PetscObject)mengine),fd);CHKERRQ(ierr); 200 PetscFunctionReturn(0); 201 } 202 203 /*@ 204 PetscMatlabEnginePut - Puts a Petsc object into the MATLAB space. For parallel objects, 205 each processors part is put in a separate MATLAB process. 206 207 Collective on PetscObject 208 209 Input Parameters: 210 + mengine - the MATLAB engine 211 - object - the PETSc object, for example Vec 212 213 Level: advanced 214 215 Note: Mats transferred between PETSc and MATLAB and vis versa are transposed in the other space 216 (this is because MATLAB uses compressed column format and PETSc uses compressed row format) 217 218 .seealso: PetscMatlabEngineDestroy(), PetscMatlabEngineCreate(), PetscMatlabEngineGet(), 219 PetscMatlabEngineEvaluate(), PetscMatlabEngineGetOutput(), PetscMatlabEnginePrintOutput(), 220 PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePutArray(), PetscMatlabEngineGetArray(), PetscMatlabEngine 221 @*/ 222 PetscErrorCode PetscMatlabEnginePut(PetscMatlabEngine mengine,PetscObject obj) 223 { 224 PetscErrorCode ierr,(*put)(PetscObject,void*); 225 226 PetscFunctionBegin; 227 ierr = PetscObjectQueryFunction(obj,"PetscMatlabEnginePut_C",&put);CHKERRQ(ierr); 228 if (!put) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Object %s cannot be put into MATLAB engine",obj->class_name); 229 ierr = PetscInfo(0,"Putting MATLAB object\n");CHKERRQ(ierr); 230 ierr = (*put)(obj,mengine->ep);CHKERRQ(ierr); 231 ierr = PetscInfo1(0,"Put MATLAB object: %s\n",obj->name);CHKERRQ(ierr); 232 PetscFunctionReturn(0); 233 } 234 235 /*@ 236 PetscMatlabEngineGet - Gets a variable from MATLAB into a PETSc object. 237 238 Collective on PetscObject 239 240 Input Parameters: 241 + mengine - the MATLAB engine 242 - object - the PETSc object, for example Vec 243 244 Level: advanced 245 246 Note: Mats transferred between PETSc and MATLAB and vis versa are transposed in the other space 247 (this is because MATLAB uses compressed column format and PETSc uses compressed row format) 248 249 .seealso: PetscMatlabEngineDestroy(), PetscMatlabEnginePut(), PetscMatlabEngineCreate(), 250 PetscMatlabEngineEvaluate(), PetscMatlabEngineGetOutput(), PetscMatlabEnginePrintOutput(), 251 PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePutArray(), PetscMatlabEngineGetArray(), PetscMatlabEngine 252 @*/ 253 PetscErrorCode PetscMatlabEngineGet(PetscMatlabEngine mengine,PetscObject obj) 254 { 255 PetscErrorCode ierr,(*get)(PetscObject,void*); 256 257 PetscFunctionBegin; 258 if (!obj->name) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Cannot get object that has no name"); 259 ierr = PetscObjectQueryFunction(obj,"PetscMatlabEngineGet_C",&get);CHKERRQ(ierr); 260 if (!get) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Object %s cannot be gotten from MATLAB engine",obj->class_name); 261 ierr = PetscInfo(0,"Getting MATLAB object\n");CHKERRQ(ierr); 262 ierr = (*get)(obj,mengine->ep);CHKERRQ(ierr); 263 ierr = PetscInfo1(0,"Got MATLAB object: %s\n",obj->name);CHKERRQ(ierr); 264 PetscFunctionReturn(0); 265 } 266 267 /* 268 The variable Petsc_Matlab_Engine_keyval is used to indicate an MPI attribute that 269 is attached to a communicator, in this case the attribute is a PetscMatlabEngine 270 */ 271 static PetscMPIInt Petsc_Matlab_Engine_keyval = MPI_KEYVAL_INVALID; 272 273 274 /*@C 275 PETSC_MATLAB_ENGINE_ - Creates a matlab engine shared by all processors 276 in a communicator. 277 278 Not Collective 279 280 Input Parameter: 281 . comm - the MPI communicator to share the engine 282 283 Level: developer 284 285 Notes: 286 Unlike almost all other PETSc routines, this does not return 287 an error code. Usually used in the form 288 $ PetscMatlabEngineYYY(XXX object,PETSC_MATLAB_ENGINE_(comm)); 289 290 .seealso: PetscMatlabEngineDestroy(), PetscMatlabEnginePut(), PetscMatlabEngineGet(), 291 PetscMatlabEngineEvaluate(), PetscMatlabEngineGetOutput(), PetscMatlabEnginePrintOutput(), 292 PetscMatlabEngineCreate(), PetscMatlabEnginePutArray(), PetscMatlabEngineGetArray(), PetscMatlabEngine, 293 PETSC_MATLAB_ENGINE_WORLD, PETSC_MATLAB_ENGINE_SELF 294 295 @*/ 296 PetscMatlabEngine PETSC_MATLAB_ENGINE_(MPI_Comm comm) 297 { 298 PetscErrorCode ierr; 299 PetscBool flg; 300 PetscMatlabEngine mengine; 301 302 PetscFunctionBegin; 303 if (Petsc_Matlab_Engine_keyval == MPI_KEYVAL_INVALID) { 304 ierr = MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN,MPI_COMM_NULL_DELETE_FN,&Petsc_Matlab_Engine_keyval,0); 305 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_MATLAB_ENGINE_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," "); mengine = 0;} 306 } 307 ierr = MPI_Comm_get_attr(comm,Petsc_Matlab_Engine_keyval,(void**)&mengine,(int*)&flg); 308 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_MATLAB_ENGINE_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," "); mengine = 0;} 309 if (!flg) { /* viewer not yet created */ 310 char *machinename = 0,machine[64]; 311 312 ierr = PetscOptionsGetString(NULL,NULL,"-matlab_engine_machine",machine,sizeof(machine),&flg); 313 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_MATLAB_ENGINE_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," "); mengine = 0;} 314 if (flg) machinename = machine; 315 ierr = PetscMatlabEngineCreate(comm,machinename,&mengine); 316 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_MATLAB_ENGINE_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," "); mengine = 0;} 317 ierr = PetscObjectRegisterDestroy((PetscObject)mengine); 318 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_MATLAB_ENGINE_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," "); mengine = 0;} 319 ierr = MPI_Comm_set_attr(comm,Petsc_Matlab_Engine_keyval,mengine); 320 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_MATLAB_ENGINE_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," "); mengine = 0;} 321 } 322 PetscFunctionReturn(mengine); 323 } 324 325 /*@C 326 PetscMatlabEnginePutArray - Puts an array into the MATLAB space, treating it as a Fortran style (column major ordering) array. For parallel objects, 327 each processors part is put in a separate MATLAB process. 328 329 Collective on PetscObject 330 331 Input Parameters: 332 + mengine - the MATLAB engine 333 . m,n - the dimensions of the array 334 . array - the array (represented in one dimension) 335 - name - the name of the array 336 337 Level: advanced 338 339 .seealso: PetscMatlabEngineDestroy(), PetscMatlabEngineCreate(), PetscMatlabEngineGet(), 340 PetscMatlabEngineEvaluate(), PetscMatlabEngineGetOutput(), PetscMatlabEnginePrintOutput(), 341 PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePut(), PetscMatlabEngineGetArray(), PetscMatlabEngine 342 @*/ 343 PetscErrorCode PetscMatlabEnginePutArray(PetscMatlabEngine mengine,int m,int n,const PetscScalar *array,const char name[]) 344 { 345 PetscErrorCode ierr; 346 mxArray *mat; 347 348 PetscFunctionBegin; 349 ierr = PetscInfo1(0,"Putting MATLAB array %s\n",name);CHKERRQ(ierr); 350 #if !defined(PETSC_USE_COMPLEX) 351 mat = mxCreateDoubleMatrix(m,n,mxREAL); 352 #else 353 mat = mxCreateDoubleMatrix(m,n,mxCOMPLEX); 354 #endif 355 ierr = PetscArraycpy(mxGetPr(mat),array,m*n);CHKERRQ(ierr); 356 engPutVariable(mengine->ep,name,mat); 357 358 ierr = PetscInfo1(0,"Put MATLAB array %s\n",name);CHKERRQ(ierr); 359 PetscFunctionReturn(0); 360 } 361 362 /*@C 363 PetscMatlabEngineGetArray - Gets a variable from Matlab into an array 364 365 Not Collective 366 367 Input Parameters: 368 + mengine - the Matlab engine 369 . m,n - the dimensions of the array 370 . array - the array (represented in one dimension) 371 - name - the name of the array 372 373 Level: advanced 374 375 .seealso: PetscMatlabEngineDestroy(), PetscMatlabEnginePut(), PetscMatlabEngineCreate(), 376 PetscMatlabEngineEvaluate(), PetscMatlabEngineGetOutput(), PetscMatlabEnginePrintOutput(), 377 PETSC_MATLAB_ENGINE_(), PetscMatlabEnginePutArray(), PetscMatlabEngineGet(), PetscMatlabEngine 378 @*/ 379 PetscErrorCode PetscMatlabEngineGetArray(PetscMatlabEngine mengine,int m,int n,PetscScalar *array,const char name[]) 380 { 381 PetscErrorCode ierr; 382 mxArray *mat; 383 384 PetscFunctionBegin; 385 ierr = PetscInfo1(0,"Getting MATLAB array %s\n",name);CHKERRQ(ierr); 386 mat = engGetVariable(mengine->ep,name); 387 if (!mat) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Unable to get array %s from matlab",name); 388 if (mxGetM(mat) != (size_t) m) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_LIB,"Array %s in matlab first dimension %d does not match requested size %d",name,(int)mxGetM(mat),m); 389 if (mxGetN(mat) != (size_t) n) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_LIB,"Array %s in matlab second dimension %d does not match requested size %d",name,(int)mxGetN(mat),m); 390 ierr = PetscArraycpy(array,mxGetPr(mat),m*n);CHKERRQ(ierr); 391 ierr = PetscInfo1(0,"Got MATLAB array %s\n",name);CHKERRQ(ierr); 392 PetscFunctionReturn(0); 393 } 394 395 396 397 398 399 400