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