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